Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/gdevtsep.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* tiffgray device:  8-bit Gray uncompressed TIFF device
18
 * tiff32nc device:  32-bit CMYK uncompressed TIFF device
19
 * tiffsep device:   Generate individual TIFF gray files for each separation
20
 *                   as well as a 'composite' 32-bit CMYK for the page.
21
 * tiffsep1 device:  Generate individual TIFF 1-bit files for each separation
22
 * tiffscaled device:Mono TIFF device (error-diffused downscaled output from
23
 *                   8-bit Gray internal rendering)
24
 * tiffscaled8 device:Greyscale TIFF device (downscaled output from
25
 *                   8-bit Gray internal rendering)
26
 * tiffscaled24 device:24-bit RGB TIFF device (dithered downscaled output
27
 *                   from 24-bit RGB internal rendering)
28
 * tiffscaled32 device:32-bit CMYK TIFF device (downscaled output
29
 *                   from 32-bit CMYK internal rendering)
30
 * tiffscaled4 device:4-bit CMYK TIFF device (dithered downscaled output
31
 *                   from 32-bit CMYK internal rendering)
32
 */
33
34
/* #define PPM_COMBINED_OUTPUT */ /* Uncomment to get PPM output similar to pknraw */
35
36
#include "stdint_.h"   /* for tiff.h */
37
#include "gdevtifs.h"
38
#include "gdevprn.h"
39
#include "gdevdevn.h"
40
#include "gsequivc.h"
41
#include "gxdht.h"
42
#include "gxiodev.h"
43
#include "gzht.h"
44
#include "stdio_.h"
45
#include "ctype_.h"
46
#include "gxgetbit.h"
47
#include "gdevppla.h"
48
#include "gxdownscale.h"
49
#include "gp.h"
50
#include "gstiffio.h"
51
#include "gscms.h"
52
#include "gsicc_cache.h"
53
#include "gxdevsop.h"
54
#include "gsicc.h"
55
56
/*
57
 * Some of the code in this module is based upon the gdevtfnx.c module.
58
 * gdevtfnx.c has the following message:
59
 * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original
60
 * version of this code to Ghostscript.
61
 */
62
63
/* ------ The device descriptors ------ */
64
65
/* Default X and Y resolution */
66
#define X_DPI 72
67
#define Y_DPI 72
68
69
/* ------ The tiffgray device ------ */
70
71
static dev_proc_print_page(tiffgray_print_page);
72
73
/* FIXME: From initial analysis this is NOT safe for bg_printing, but might be fixable */
74
static void
75
tiffgray_initialize_device_procs(gx_device *dev)
76
0
{
77
0
    gdev_prn_initialize_device_procs_gray(dev);
78
79
0
    set_dev_proc(dev, open_device, tiff_open);
80
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
81
0
    set_dev_proc(dev, close_device, tiff_close);
82
0
    set_dev_proc(dev, get_params, tiff_get_params);
83
0
    set_dev_proc(dev, put_params, tiff_put_params);
84
0
    set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color);
85
0
    set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray);
86
0
}
87
88
const gx_device_tiff gs_tiffgray_device = {
89
    prn_device_body(gx_device_tiff, tiffgray_initialize_device_procs, "tiffgray",
90
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
91
                    X_DPI, Y_DPI,
92
                    0, 0, 0, 0, /* Margins */
93
                    1, 8, 255, 0, 256, 0, tiffgray_print_page),
94
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
95
    false,                      /* default to *not* bigtiff */
96
    COMPRESSION_NONE,
97
    TIFF_DEFAULT_STRIP_SIZE,
98
    0, /* Adjust size */
99
    true, /* write_datetime */
100
    GX_DOWNSCALER_PARAMS_DEFAULTS,
101
    0
102
};
103
104
static int
105
tiffscaled_spec_op(gx_device *dev_, int op, void *data, int datasize)
106
0
{
107
0
    if (op == gxdso_supports_iccpostrender) {
108
0
        return true;
109
0
    }
110
0
    return gdev_prn_dev_spec_op(dev_, op, data, datasize);
111
0
}
112
113
/* ------ The tiffscaled device ------ */
114
115
dev_proc_open_device(tiff_open_s);
116
static dev_proc_print_page(tiffscaled_print_page);
117
static int tiff_set_icc_color_fields(gx_device_printer *pdev);
118
119
static void
120
tiffscaled_initialize_device_procs(gx_device *dev)
121
0
{
122
0
    gdev_prn_initialize_device_procs_gray(dev);
123
124
0
    set_dev_proc(dev, open_device, tiff_open);
125
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
126
0
    set_dev_proc(dev, close_device, tiff_close);
127
0
    set_dev_proc(dev, get_params, tiff_get_params_downscale);
128
0
    set_dev_proc(dev, put_params, tiff_put_params_downscale);
129
0
    set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color);
130
0
    set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray);
131
0
}
132
133
const gx_device_tiff gs_tiffscaled_device = {
134
    prn_device_body(gx_device_tiff,
135
                    tiffscaled_initialize_device_procs,
136
                    "tiffscaled",
137
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
138
                    600, 600,   /* 600 dpi by default */
139
                    0, 0, 0, 0, /* Margins */
140
                    1,          /* num components */
141
                    8,          /* bits per sample */
142
                    255, 0, 256, 0,
143
                    tiffscaled_print_page),
144
    ARCH_IS_BIG_ENDIAN,/* default to native endian (i.e. use big endian iff the platform is so */
145
    false,             /* default to not bigtiff */
146
    COMPRESSION_NONE,
147
    TIFF_DEFAULT_STRIP_SIZE,
148
    0, /* Adjust size */
149
    true, /* write_datetime */
150
    GX_DOWNSCALER_PARAMS_DEFAULTS,
151
    0
152
};
153
154
/* ------ The tiffscaled8 device ------ */
155
156
static dev_proc_print_page(tiffscaled8_print_page);
157
158
static void
159
tiffscaled8_initialize_device_procs(gx_device *dev)
160
0
{
161
0
    gdev_prn_initialize_device_procs_gray(dev);
162
163
0
    set_dev_proc(dev, open_device, tiff_open_s);
164
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
165
0
    set_dev_proc(dev, close_device, tiff_close);
166
0
    set_dev_proc(dev, get_params, tiff_get_params_downscale);
167
0
    set_dev_proc(dev, put_params, tiff_put_params_downscale);
168
0
    set_dev_proc(dev, dev_spec_op, tiffscaled_spec_op);
169
0
    set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color);
170
0
    set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray);
171
0
}
172
173
const gx_device_tiff gs_tiffscaled8_device = {
174
    prn_device_body(gx_device_tiff,
175
                    tiffscaled8_initialize_device_procs,
176
                    "tiffscaled8",
177
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
178
                    600, 600,   /* 600 dpi by default */
179
                    0, 0, 0, 0, /* Margins */
180
                    1,          /* num components */
181
                    8,          /* bits per sample */
182
                    255, 0, 256, 0,
183
                    tiffscaled8_print_page),
184
    ARCH_IS_BIG_ENDIAN,/* default to native endian (i.e. use big endian iff the platform is so */
185
    false,             /* default to not bigtiff */
186
    COMPRESSION_NONE,
187
    TIFF_DEFAULT_STRIP_SIZE,
188
    0, /* Adjust size */
189
    true, /* write_datetime */
190
    GX_DOWNSCALER_PARAMS_DEFAULTS,
191
    0
192
};
193
194
/* ------ The tiffscaled24 device ------ */
195
196
static dev_proc_print_page(tiffscaled24_print_page);
197
198
static void
199
tiffscaled24_initialize_device_procs(gx_device *dev)
200
0
{
201
0
    gdev_prn_initialize_device_procs_rgb(dev);
202
203
0
    set_dev_proc(dev, open_device, tiff_open_s);
204
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
205
0
    set_dev_proc(dev, close_device, tiff_close);
206
0
    set_dev_proc(dev, get_params, tiff_get_params_downscale);
207
0
    set_dev_proc(dev, put_params, tiff_put_params_downscale);
208
0
    set_dev_proc(dev, dev_spec_op, tiffscaled_spec_op);
209
0
    set_dev_proc(dev, encode_color, gx_default_rgb_map_rgb_color);
210
0
    set_dev_proc(dev, decode_color, gx_default_rgb_map_color_rgb);
211
0
}
212
213
const gx_device_tiff gs_tiffscaled24_device = {
214
    prn_device_body(gx_device_tiff,
215
                    tiffscaled24_initialize_device_procs,
216
                    "tiffscaled24",
217
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
218
                    600, 600,   /* 600 dpi by default */
219
                    0, 0, 0, 0, /* Margins */
220
                    3,          /* num components */
221
                    24,         /* bits per sample */
222
                    255, 255, 256, 256,
223
                    tiffscaled24_print_page),
224
    ARCH_IS_BIG_ENDIAN,/* default to native endian (i.e. use big endian iff the platform is so */
225
    false,             /* default to not bigtiff */
226
    COMPRESSION_NONE,
227
    TIFF_DEFAULT_STRIP_SIZE,
228
    0, /* Adjust size */
229
    true, /* write_datetime */
230
    GX_DOWNSCALER_PARAMS_DEFAULTS,
231
    0
232
};
233
234
/* ------ The tiffscaled32 device ------ */
235
236
static dev_proc_print_page(tiffscaled32_print_page);
237
238
static void
239
tiffscaled32_initialize_device_procs(gx_device *dev)
240
0
{
241
0
    gdev_prn_initialize_device_procs_cmyk8(dev);
242
243
0
    set_dev_proc(dev, open_device, tiff_open_s);
244
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
245
0
    set_dev_proc(dev, close_device, tiff_close);
246
0
    set_dev_proc(dev, get_params, tiff_get_params_downscale_cmyk);
247
0
    set_dev_proc(dev, put_params, tiff_put_params_downscale_cmyk);
248
0
    set_dev_proc(dev, dev_spec_op, tiffscaled_spec_op);
249
0
    set_dev_proc(dev, encode_color, cmyk_8bit_map_cmyk_color);
250
0
    set_dev_proc(dev, decode_color, cmyk_8bit_map_color_cmyk);
251
0
}
252
253
const gx_device_tiff gs_tiffscaled32_device = {
254
    prn_device_body(gx_device_tiff,
255
                    tiffscaled32_initialize_device_procs,
256
                    "tiffscaled32",
257
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
258
                    600, 600,   /* 600 dpi by default */
259
                    0, 0, 0, 0, /* Margins */
260
                    4,          /* num components */
261
                    32,         /* bits per sample */
262
                    255, 255, 256, 256,
263
                    tiffscaled32_print_page),
264
    ARCH_IS_BIG_ENDIAN,/* default to native endian (i.e. use big endian iff the platform is so */
265
    false,             /* default to not bigtiff */
266
    COMPRESSION_NONE,
267
    TIFF_DEFAULT_STRIP_SIZE,
268
    0, /* Adjust size */
269
    true, /* write_datetime */
270
    GX_DOWNSCALER_PARAMS_DEFAULTS,
271
    0
272
};
273
274
/* ------ The tiffscaled4 device ------ */
275
276
static dev_proc_print_page(tiffscaled4_print_page);
277
278
static void
279
tiffscaled4_initialize_device_procs(gx_device *dev)
280
0
{
281
0
    gdev_prn_initialize_device_procs_cmyk8(dev);
282
283
0
    set_dev_proc(dev, open_device, tiff_open);
284
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
285
0
    set_dev_proc(dev, close_device, tiff_close);
286
0
    set_dev_proc(dev, get_params, tiff_get_params_downscale_cmyk_ets);
287
0
    set_dev_proc(dev, put_params, tiff_put_params_downscale_cmyk_ets);
288
0
}
289
290
const gx_device_tiff gs_tiffscaled4_device = {
291
    prn_device_body(gx_device_tiff,
292
                    tiffscaled4_initialize_device_procs,
293
                    "tiffscaled4",
294
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
295
                    600, 600,   /* 600 dpi by default */
296
                    0, 0, 0, 0, /* Margins */
297
                    4,          /* num components */
298
                    32,         /* bits per sample */
299
                    255, 255, 256, 256,
300
                    tiffscaled4_print_page),
301
    ARCH_IS_BIG_ENDIAN,/* default to native endian (i.e. use big endian iff the platform is so */
302
    false,             /* default to not bigtiff */
303
    COMPRESSION_NONE,
304
    TIFF_DEFAULT_STRIP_SIZE,
305
    0, /* Adjust size */
306
    true, /* write_datetime */
307
    GX_DOWNSCALER_PARAMS_DEFAULTS,
308
    0
309
};
310
311
/* ------ Private functions ------ */
312
313
static void
314
tiff_set_gray_fields(gx_device_printer *pdev, TIFF *tif,
315
                     unsigned short bits_per_sample,
316
                     int compression,
317
                     long max_strip_size)
318
914
{
319
914
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
320
914
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
321
914
    TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
322
914
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
323
324
914
    tiff_set_compression(pdev, tif, compression, max_strip_size);
325
914
}
326
327
static int
328
tiffgray_print_page(gx_device_printer * pdev, gp_file * file)
329
0
{
330
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
331
0
    int code;
332
333
0
    if (!tfdev->UseBigTIFF && tfdev->Compression==COMPRESSION_NONE &&
334
0
        pdev->height > ((unsigned long) 0xFFFFFFFF - gp_ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
335
0
        return_error(gs_error_rangecheck);  /* this will overflow 32 bits */
336
337
0
    code = gdev_tiff_begin_page(tfdev, file);
338
0
    if (code < 0)
339
0
        return code;
340
341
0
    tiff_set_gray_fields(pdev, tfdev->tif, 8, tfdev->Compression, tfdev->MaxStripSize);
342
343
0
    return tiff_print_page(pdev, tfdev->tif, 0);
344
0
}
345
346
static int
347
tiffscaled_print_page(gx_device_printer * pdev, gp_file * file)
348
0
{
349
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
350
0
    int code;
351
352
0
    code = gdev_tiff_begin_page(tfdev, file);
353
0
    if (code < 0)
354
0
        return code;
355
356
0
    tiff_set_gray_fields(pdev, tfdev->tif, 1, tfdev->Compression,
357
0
        tfdev->MaxStripSize);
358
359
360
0
    return tiff_downscale_and_print_page(pdev, tfdev->tif,
361
0
                                         &tfdev->downscale,
362
0
                                         tfdev->AdjustWidth,
363
0
                                         1, 1);
364
0
}
365
366
static int
367
tiffscaled8_print_page(gx_device_printer * pdev, gp_file * file)
368
0
{
369
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
370
0
    int code;
371
372
0
    code = gdev_tiff_begin_page(tfdev, file);
373
0
    if (code < 0)
374
0
        return code;
375
376
0
    if (tfdev->icclink != NULL && tfdev->icclink->num_output != 1)
377
0
    {
378
0
        code = tiff_set_icc_color_fields(pdev);
379
0
        if (code < 0)
380
0
            return code;
381
0
    } else {
382
0
        tiff_set_gray_fields(pdev, tfdev->tif, 8, tfdev->Compression,
383
0
            tfdev->MaxStripSize);
384
0
    }
385
0
    return tiff_downscale_and_print_page(pdev, tfdev->tif,
386
0
                                         &tfdev->downscale,
387
0
                                         tfdev->AdjustWidth,
388
0
                                         8, 1);
389
0
}
390
391
static void
392
tiff_set_rgb_fields(gx_device_tiff *tfdev)
393
0
{
394
0
    cmm_profile_t *icc_profile;
395
396
0
    if (tfdev->icc_struct->postren_profile != NULL)
397
0
        icc_profile = tfdev->icc_struct->postren_profile;
398
0
    else
399
0
        icc_profile = tfdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
400
401
0
    switch (icc_profile->data_cs) {
402
0
        case gsRGB:
403
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
404
0
            break;
405
0
        case gsCIELAB:
406
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB);
407
0
            break;
408
0
        default:
409
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
410
0
            break;
411
0
    }
412
0
    TIFFSetField(tfdev->tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
413
0
    TIFFSetField(tfdev->tif, TIFFTAG_SAMPLESPERPIXEL, 3);
414
415
0
    tiff_set_compression((gx_device_printer *)tfdev, tfdev->tif,
416
0
                         tfdev->Compression, tfdev->MaxStripSize);
417
0
}
418
419
420
static int
421
tiffscaled24_print_page(gx_device_printer * pdev, gp_file * file)
422
0
{
423
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
424
0
    int code;
425
426
0
    code = gdev_tiff_begin_page(tfdev, file);
427
0
    if (code < 0)
428
0
        return code;
429
430
0
    if (tfdev->icclink != NULL && tfdev->icclink->num_output != 3) {
431
0
        code = tiff_set_icc_color_fields(pdev);
432
0
        if (code < 0)
433
0
            return code;
434
0
    } else {
435
0
        TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE, 8);
436
0
        tiff_set_rgb_fields(tfdev);
437
0
    }
438
439
0
    return tiff_downscale_and_print_page(pdev, tfdev->tif,
440
0
                                         &tfdev->downscale,
441
0
                                         tfdev->AdjustWidth,
442
0
                                         8, 3);
443
0
}
444
445
static void
446
tiff_set_cmyk_fields(gx_device_printer *pdev, TIFF *tif,
447
                     short bits_per_sample,
448
                     uint16_t compression,
449
                     long max_strip_size)
450
0
{
451
0
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
452
0
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED);
453
0
    TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
454
0
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4);
455
456
0
    tiff_set_compression(pdev, tif, compression, max_strip_size);
457
0
}
458
459
static int
460
tiffscaled32_print_page(gx_device_printer * pdev, gp_file * file)
461
0
{
462
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
463
0
    int code;
464
465
0
    code = gdev_tiff_begin_page(tfdev, file);
466
0
    if (code < 0)
467
0
        return code;
468
469
0
    if (tfdev->icclink != NULL && tfdev->icclink->num_output != 4)
470
0
    {
471
0
        code = tiff_set_icc_color_fields(pdev);
472
0
        if (code < 0)
473
0
            return code;
474
0
    } else {
475
0
        tiff_set_cmyk_fields(pdev, tfdev->tif, 8, tfdev->Compression,
476
0
            tfdev->MaxStripSize);
477
0
    }
478
479
0
    return tiff_downscale_and_print_page(pdev, tfdev->tif,
480
0
                                         &tfdev->downscale,
481
0
                                         tfdev->AdjustWidth,
482
0
                                         8, 4);
483
0
}
484
485
static int
486
tiffscaled4_print_page(gx_device_printer * pdev, gp_file * file)
487
0
{
488
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
489
0
    int code;
490
491
0
    code = gdev_tiff_begin_page(tfdev, file);
492
0
    if (code < 0)
493
0
        return code;
494
495
0
    tiff_set_cmyk_fields(pdev,
496
0
                         tfdev->tif,
497
0
                         1,
498
0
                         tfdev->Compression,
499
0
                         tfdev->MaxStripSize);
500
501
0
    return tiff_downscale_and_print_page(pdev, tfdev->tif,
502
0
                                         &tfdev->downscale,
503
0
                                         tfdev->AdjustWidth,
504
0
                                         1, 4);
505
0
}
506
507
/* Called when the post render ICC profile is in a different color space
508
* type compared to the output ICC profile (e.g. cmyk vs rgb) */
509
static int
510
tiff_set_icc_color_fields(gx_device_printer *pdev)
511
0
{
512
0
    gx_device_tiff *tfdev = (gx_device_tiff *)pdev;
513
514
0
    TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE, 8);
515
0
    switch (tfdev->icclink->num_output)
516
0
    {
517
0
    case 1:
518
0
        tiff_set_gray_fields(pdev, tfdev->tif, 8, tfdev->Compression,
519
0
            tfdev->MaxStripSize);
520
0
        break;
521
0
    case 3:
522
0
        tiff_set_rgb_fields(tfdev);
523
0
        break;
524
0
    case 4:
525
0
        tiff_set_cmyk_fields(pdev, tfdev->tif,
526
0
            pdev->color_info.depth / pdev->color_info.num_components,
527
0
            tfdev->Compression, tfdev->MaxStripSize);
528
0
        break;
529
0
    default:
530
0
        return gs_error_undefined;
531
0
    }
532
0
    return 0;
533
0
}
534
535
static int
536
tiffsep_spec_op(gx_device *dev_, int op, void *data, int datasize)
537
1.16M
{
538
1.16M
    if (op == gxdso_supports_iccpostrender || op == gxdso_supports_devn
539
1.16M
     || op == gxdso_skip_icc_component_validation) {
540
616
        return true;
541
616
    }
542
1.16M
    return gdev_prn_dev_spec_op(dev_, op, data, datasize);
543
1.16M
}
544
545
/* ------ The cmyk devices ------ */
546
547
static dev_proc_print_page(tiffcmyk_print_page);
548
549
/* 8-bit-per-plane separated CMYK color. */
550
551
static void
552
tiffcmyk_initialize_device_procs(gx_device *dev)
553
0
{
554
0
    gdev_prn_initialize_device_procs_cmyk8(dev);
555
556
0
    set_dev_proc(dev, open_device, tiff_open);
557
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
558
0
    set_dev_proc(dev, close_device, tiff_close);
559
0
    set_dev_proc(dev, get_params, tiff_get_params);
560
0
    set_dev_proc(dev, put_params, tiff_put_params);
561
0
}
562
563
const gx_device_tiff gs_tiff32nc_device = {
564
    prn_device_body(gx_device_tiff, tiffcmyk_initialize_device_procs, "tiff32nc",
565
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
566
                    X_DPI, Y_DPI,
567
                    0, 0, 0, 0, /* Margins */
568
                    4, 32, 255, 255, 256, 256, tiffcmyk_print_page),
569
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
570
    false,                      /* default to not bigtiff */
571
    COMPRESSION_NONE,
572
    TIFF_DEFAULT_STRIP_SIZE,
573
    0, /* Adjust size */
574
    true, /* write_datetime */
575
    GX_DOWNSCALER_PARAMS_DEFAULTS,
576
    0
577
};
578
579
/* 16-bit-per-plane separated CMYK color. */
580
581
static void
582
tiff64_initialize_device_procs(gx_device *dev)
583
0
{
584
0
    gdev_prn_initialize_device_procs_cmyk16(dev);
585
586
0
    set_dev_proc(dev, open_device, tiff_open);
587
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
588
0
    set_dev_proc(dev, close_device, tiff_close);
589
0
    set_dev_proc(dev, get_params, tiff_get_params);
590
0
    set_dev_proc(dev, put_params, tiff_put_params);
591
0
}
592
593
const gx_device_tiff gs_tiff64nc_device = {
594
    prn_device_body(gx_device_tiff, tiff64_initialize_device_procs, "tiff64nc",
595
                    DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
596
                    X_DPI, Y_DPI,
597
                    0, 0, 0, 0, /* Margins */
598
                    4, 64, 255, 255, 256, 256, tiffcmyk_print_page),
599
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
600
    false,                      /* default to not bigtiff */
601
    COMPRESSION_NONE,
602
    TIFF_DEFAULT_STRIP_SIZE,
603
    0, /* Adjust size */
604
    false, /* write_datetime */
605
    GX_DOWNSCALER_PARAMS_DEFAULTS,
606
    0
607
};
608
609
/* ------ Private functions ------ */
610
611
static int
612
tiffcmyk_print_page(gx_device_printer * pdev, gp_file * file)
613
0
{
614
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
615
0
    int code;
616
617
0
    if (!tfdev->UseBigTIFF && tfdev->Compression==COMPRESSION_NONE &&
618
0
        pdev->height > ((unsigned long) 0xFFFFFFFF - gp_ftell(file))/(pdev->width)) /* note width is never 0 in print_page */
619
0
        return_error(gs_error_rangecheck);  /* this will overflow 32 bits */
620
621
0
    code = gdev_tiff_begin_page(tfdev, file);
622
0
    if (code < 0)
623
0
        return code;
624
625
0
    tiff_set_cmyk_fields(pdev,
626
0
                         tfdev->tif,
627
0
                         pdev->color_info.depth / pdev->color_info.num_components,
628
0
                         tfdev->Compression,
629
0
                         tfdev->MaxStripSize);
630
631
0
    return tiff_print_page(pdev, tfdev->tif, 0);
632
0
}
633
634
/* ----------  The tiffsep device ------------ */
635
636
0
#define NUM_CMYK_COMPONENTS 4
637
0
#define MAX_COLOR_VALUE 255             /* We are using 8 bits per colorant */
638
639
/* The device descriptor */
640
static dev_proc_open_device(tiffsep_prn_open);
641
static dev_proc_close_device(tiffsep_prn_close);
642
static dev_proc_get_params(tiffsep_get_params);
643
static dev_proc_put_params(tiffsep_put_params);
644
static dev_proc_print_page(tiffsep_print_page);
645
static dev_proc_get_color_mapping_procs(tiffsep_get_color_mapping_procs);
646
static dev_proc_get_color_comp_index(tiffsep_get_color_comp_index);
647
static dev_proc_encode_color(tiffsep_encode_color);
648
static dev_proc_decode_color(tiffsep_decode_color);
649
static dev_proc_update_spot_equivalent_colors(tiffsep_update_spot_equivalent_colors);
650
static dev_proc_ret_devn_params(tiffsep_ret_devn_params);
651
static dev_proc_ret_devn_params_const(tiffsep_ret_devn_params_const);
652
static dev_proc_open_device(tiffsep1_prn_open);
653
static dev_proc_close_device(tiffsep1_prn_close);
654
static dev_proc_print_page(tiffsep1_print_page);
655
static dev_proc_encode_color(tiffsep1_encode_color);
656
static dev_proc_decode_color(tiffsep1_decode_color);
657
658
/* common to tiffsep and tiffsepo1 */
659
#define tiffsep_devices_common\
660
    gx_device_common;\
661
    gx_prn_device_common;\
662
        /* tiff state for separation files */\
663
    gp_file *sep_file[GX_DEVICE_COLOR_MAX_COMPONENTS];\
664
    TIFF *tiff[GX_DEVICE_COLOR_MAX_COMPONENTS]; \
665
    bool  NoSeparationFiles;    /* true = no separation files created only a composite file */\
666
    bool  BigEndian;            /* true = big endian; false = little endian */\
667
    bool  UseBigTIFF;           /* true = output bigtiff, false don't */ \
668
    bool  write_datetime;       /* true = write DATETIME tag, false = don't */ \
669
    bool  PrintSpotCMYK;        /* true = print CMYK equivalents for spot inks; false = do nothing */\
670
    uint16_t Compression;         /* for the separation files, same values as TIFFTAG_COMPRESSION */\
671
    long MaxStripSize;\
672
    long BitsPerComponent;\
673
    int max_spots;\
674
    bool lock_colorants;\
675
    gx_downscaler_params downscale;\
676
    gs_devn_params devn_params;         /* DeviceN generated parameters */\
677
    equivalent_cmyk_color_params equiv_cmyk_colors;\
678
    bool warning_given;   /* avoid issuing lots of warnings */\
679
    gp_file *comp_file;            /* Underlying file for tiff_comp */\
680
    TIFF *tiff_comp;            /* tiff file for comp file */\
681
    gsicc_link_t *icclink;      /* link profile if we are doing post rendering */\
682
    unsigned int page_num_comps    /* Number of components at end of page, for cleanup */
683
684
/*
685
 * A structure definition for a DeviceN type device
686
 */
687
typedef struct tiffsep_device_s {
688
    tiffsep_devices_common;
689
} tiffsep_device;
690
691
typedef struct tiffsep1_device_s {
692
    tiffsep_devices_common;
693
} tiffsep1_device;
694
695
/* GC procedures */
696
static
697
31.4k
ENUM_PTRS_WITH(tiffsep_device_enum_ptrs, tiffsep_device *pdev)
698
31.4k
{
699
31.4k
    if (index < pdev->devn_params.separations.num_separations)
700
0
        ENUM_RETURN(pdev->devn_params.separations.names[index].data);
701
31.4k
    ENUM_PREFIX(st_device_printer,
702
0
                    pdev->devn_params.separations.num_separations);
703
0
    return 0;
704
31.4k
}
705
31.4k
ENUM_PTRS_END
706
707
616
static RELOC_PTRS_WITH(tiffsep_device_reloc_ptrs, tiffsep_device *pdev)
708
616
{
709
616
    RELOC_PREFIX(st_device_printer);
710
616
    {
711
616
        int i;
712
713
616
        for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
714
0
            RELOC_PTR(tiffsep_device, devn_params.separations.names[i].data);
715
0
        }
716
616
    }
717
616
}
718
616
RELOC_PTRS_END
719
720
/* Even though tiffsep_device_finalize is the same as gx_device_finalize, */
721
/* we need to implement it separately because st_composite_final */
722
/* declares all 3 procedures as private. */
723
static void
724
tiffsep_device_finalize(const gs_memory_t *cmem, void *vpdev)
725
308
{
726
    /* We need to deallocate the names. */
727
308
    devn_free_params((gx_device*) vpdev);
728
308
    gx_device_finalize(cmem, vpdev);
729
308
}
730
731
gs_private_st_composite_final(st_tiffsep_device, tiffsep_device,
732
    "tiffsep_device", tiffsep_device_enum_ptrs, tiffsep_device_reloc_ptrs,
733
    tiffsep_device_finalize);
734
735
static void
736
tiffsep_initialize_device_procs(gx_device *dev)
737
308
{
738
308
    gdev_prn_initialize_device_procs(dev);
739
740
308
    set_dev_proc(dev, open_device, tiffsep_prn_open);
741
308
    set_dev_proc(dev, close_device, tiffsep_prn_close);
742
308
    set_dev_proc(dev, map_color_rgb, tiffsep_decode_color);
743
308
    set_dev_proc(dev, get_params, tiffsep_get_params);
744
308
    set_dev_proc(dev, put_params, tiffsep_put_params);
745
308
    set_dev_proc(dev, get_color_mapping_procs, tiffsep_get_color_mapping_procs);
746
308
    set_dev_proc(dev, get_color_comp_index, tiffsep_get_color_comp_index);
747
308
    set_dev_proc(dev, encode_color, tiffsep_encode_color);
748
308
    set_dev_proc(dev, decode_color, tiffsep_decode_color);
749
308
    set_dev_proc(dev, update_spot_equivalent_colors, tiffsep_update_spot_equivalent_colors);
750
308
    set_dev_proc(dev, ret_devn_params, tiffsep_ret_devn_params);
751
308
    set_dev_proc(dev, dev_spec_op, tiffsep_spec_op);
752
308
}
753
754
static void
755
tiffsep1_initialize_device_procs(gx_device *dev)
756
308
{
757
308
    tiffsep_initialize_device_procs(dev);
758
308
    set_dev_proc(dev, open_device, tiffsep1_prn_open);
759
308
    set_dev_proc(dev, close_device, tiffsep1_prn_close);
760
308
    set_dev_proc(dev, encode_color, tiffsep1_encode_color);
761
308
    set_dev_proc(dev, decode_color, tiffsep1_decode_color);
762
308
    set_dev_proc(dev, map_color_rgb, cmyk_1bit_map_color_rgb);
763
308
}
764
765
#define tiffsep_devices_body(dtype, procs, dname, ncomp, pol, depth, mg, mc, sl, cn, print_page, compr, bpc)\
766
    std_device_full_body_type_extended(dtype, &procs, dname,\
767
          &st_tiffsep_device,\
768
          (int)((long)(DEFAULT_WIDTH_10THS) * (X_DPI) / 10),\
769
          (int)((long)(DEFAULT_HEIGHT_10THS) * (Y_DPI) / 10),\
770
          X_DPI, Y_DPI,\
771
          ncomp,                /* MaxComponents */\
772
          ncomp,                /* NumComp */\
773
          pol,                  /* Polarity */\
774
          depth, 0,             /* Depth, GrayIndex */\
775
          mg, mc,               /* MaxGray, MaxColor */\
776
          mg + 1, mc + 1,       /* DitherGray, DitherColor */\
777
          sl,                   /* Linear & Separable? */\
778
          cn,                   /* Process color model name */\
779
          0, 0,                 /* offsets */\
780
          0, 0, 0, 0            /* margins */\
781
        ),\
782
        prn_device_body_rest_(print_page),\
783
        { 0 },                  /* tiff state for separation files */\
784
        { 0 },                  /* separation files */\
785
        false,                  /* NoSeparationFiles */\
786
        ARCH_IS_BIG_ENDIAN      /* true = big endian; false = little endian */,\
787
        false,                  /* UseBigTIFF */\
788
        true,                   /* write_datetime */ \
789
        false,                  /* PrintSpotCMYK */\
790
        compr                   /* COMPRESSION_* */,\
791
        TIFF_DEFAULT_STRIP_SIZE,/* MaxStripSize */\
792
        bpc,                      /* BitsPerComponent */\
793
        GS_SOFT_MAX_SPOTS,      /* max_spots */\
794
        false,                  /* Colorants not locked */\
795
        GX_DOWNSCALER_PARAMS_DEFAULTS
796
797
#define GCIB (ARCH_SIZEOF_GX_COLOR_INDEX * 8)
798
799
/*
800
 * TIFF devices with CMYK process color model and spot color support.
801
 */
802
const tiffsep_device gs_tiffsep_device =
803
{
804
    tiffsep_devices_body(tiffsep_device, tiffsep_initialize_device_procs, "tiffsep", ARCH_SIZEOF_GX_COLOR_INDEX, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, MAX_COLOR_VALUE, MAX_COLOR_VALUE, GX_CINFO_SEP_LIN, "DeviceCMYK", tiffsep_print_page, COMPRESSION_LZW, 8),
805
    /* devn_params specific parameters */
806
    { 8,                        /* Bits per color */
807
      DeviceCMYKComponents,     /* Names of color model colorants */
808
      4,                        /* Number colorants for CMYK */
809
      0,                        /* MaxSeparations has not been specified */
810
      -1,                       /* PageSpotColors has not been specified */
811
      {0},                      /* SeparationNames */
812
      0,                        /* SeparationOrder names */
813
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
814
    },
815
    { true },                   /* equivalent CMYK colors for spot colors */
816
    false,      /* warning_given */
817
};
818
819
const tiffsep1_device gs_tiffsep1_device =
820
{
821
    tiffsep_devices_body(tiffsep1_device, tiffsep1_initialize_device_procs, "tiffsep1", ARCH_SIZEOF_GX_COLOR_INDEX, GX_CINFO_POLARITY_SUBTRACTIVE, GCIB, 1, 1, GX_CINFO_SEP_LIN, "DeviceCMYK", tiffsep1_print_page, COMPRESSION_CCITTFAX4, 1),
822
    /* devn_params specific parameters */
823
    { 1,                        /* Bits per color */
824
      DeviceCMYKComponents,     /* Names of color model colorants */
825
      4,                        /* Number colorants for CMYK */
826
      0,                        /* MaxSeparations has not been specified */
827
      -1,                       /* PageSpotColors has not been specified */
828
      {0},                      /* SeparationNames */
829
      0,                        /* SeparationOrder names */
830
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
831
    },
832
    { true },                   /* equivalent CMYK colors for spot colors */
833
    false,                      /* warning_given */
834
};
835
836
#undef GCIB
837
838
/*
839
 * The following procedures are used to map the standard color spaces into
840
 * the color components for the tiffsep device.
841
 */
842
static void
843
tiffsep_gray_cs_to_cm(const gx_device * dev, frac gray, frac out[])
844
783
{
845
783
    int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
846
847
783
    gray_cs_to_devn_cm(dev, map, gray, out);
848
783
}
849
850
static void
851
tiffsep_rgb_cs_to_cm(const gx_device * dev, const gs_gstate *pgs,
852
                                   frac r, frac g, frac b, frac out[])
853
0
{
854
0
    int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
855
856
0
    rgb_cs_to_devn_cm(dev, map, pgs, r, g, b, out);
857
0
}
858
859
static void
860
tiffsep_cmyk_cs_to_cm(const gx_device * dev,
861
                frac c, frac m, frac y, frac k, frac out[])
862
13.2M
{
863
13.2M
    const gs_devn_params *devn = tiffsep_ret_devn_params_const(dev);
864
13.2M
    const int *map = devn->separation_order_map;
865
13.2M
    int j;
866
867
13.2M
    if (devn->num_separation_order_names > 0) {
868
869
        /* We need to make sure to clear everything */
870
0
        for (j = 0; j < dev->color_info.num_components; j++)
871
0
            out[j] = frac_0;
872
873
0
        for (j = 0; j < devn->num_separation_order_names; j++) {
874
0
            switch (map[j]) {
875
0
                case 0 :
876
0
                    out[0] = c;
877
0
                    break;
878
0
                case 1:
879
0
                    out[1] = m;
880
0
                    break;
881
0
                case 2:
882
0
                    out[2] = y;
883
0
                    break;
884
0
                case 3:
885
0
                    out[3] = k;
886
0
                    break;
887
0
                default:
888
0
                    break;
889
0
            }
890
0
        }
891
13.2M
    } else {
892
13.2M
        cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
893
13.2M
    }
894
13.2M
}
895
896
static const gx_cm_color_map_procs tiffsep_cm_procs = {
897
    tiffsep_gray_cs_to_cm,
898
    tiffsep_rgb_cs_to_cm,
899
    tiffsep_cmyk_cs_to_cm
900
};
901
902
/*
903
 * These are the handlers for returning the list of color space
904
 * to color model conversion routines.
905
 */
906
static const gx_cm_color_map_procs *
907
tiffsep_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev)
908
13.2M
{
909
13.2M
    *tdev = dev;
910
13.2M
    return &tiffsep_cm_procs;
911
13.2M
}
912
913
/*
914
 * Encode a list of colorant values into a gx_color_index_value.
915
 * With 32 bit gx_color_index values, we simply pack values.
916
 */
917
static gx_color_index
918
tiffsep_encode_color(gx_device *dev, const gx_color_value colors[])
919
0
{
920
0
    int bpc = ((tiffsep_device *)dev)->devn_params.bitspercomponent;
921
0
    gx_color_index color = 0;
922
0
    int i = 0;
923
0
    int ncomp = dev->color_info.num_components;
924
0
    COLROUND_VARS;
925
926
0
    COLROUND_SETUP(bpc);
927
0
    for (; i < ncomp; i++) {
928
0
        color <<= bpc;
929
0
        color |= COLROUND_ROUND(colors[i]);
930
0
    }
931
0
    return (color == gx_no_color_index ? color ^ 1 : color);
932
0
}
933
934
/*
935
 * Decode a gx_color_index value back to a list of colorant values.
936
 * With 32 bit gx_color_index values, we simply pack values.
937
 */
938
static int
939
tiffsep_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
940
0
{
941
0
    int bpc = ((tiffsep_device *)dev)->devn_params.bitspercomponent;
942
0
    int drop = sizeof(gx_color_value) * 8 - bpc;
943
0
    int mask = (1 << bpc) - 1;
944
0
    int i = 0;
945
0
    int ncomp = dev->color_info.num_components;
946
947
0
    for (; i < ncomp; i++) {
948
0
        out[ncomp - i - 1] = (gx_color_value) ((color & mask) << drop);
949
0
        color >>= bpc;
950
0
    }
951
0
    return 0;
952
0
}
953
954
/*
955
 *  Device proc for updating the equivalent CMYK color for spot colors.
956
 */
957
static int
958
tiffsep_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs, const gs_color_space *pcs)
959
742
{
960
742
    tiffsep_device * pdev = (tiffsep_device *)dev;
961
962
742
    update_spot_equivalent_cmyk_colors(dev, pgs, pcs,
963
742
                    &pdev->devn_params, &pdev->equiv_cmyk_colors);
964
742
    return 0;
965
742
}
966
967
/*
968
 *  Device proc for returning a pointer to DeviceN parameter structure
969
 */
970
static gs_devn_params *
971
tiffsep_ret_devn_params(gx_device * dev)
972
469k
{
973
469k
    tiffsep_device * pdev = (tiffsep_device *)dev;
974
975
469k
    return &pdev->devn_params;
976
469k
}
977
978
static const gs_devn_params *
979
tiffsep_ret_devn_params_const (const gx_device * dev)
980
13.2M
{
981
13.2M
    const tiffsep_device * pdev = (const tiffsep_device *)dev;
982
983
13.2M
    return &pdev->devn_params;
984
13.2M
}
985
986
/* Get parameters.  We provide a default CRD. */
987
static int
988
tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
989
8.82k
{
990
8.82k
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
991
8.82k
    int code = gdev_prn_get_params(pdev, plist);
992
8.82k
    int ecode = code;
993
8.82k
    gs_param_string comprstr;
994
995
8.82k
    if (code < 0)
996
0
        return code;
997
998
8.82k
    code = devn_get_params(pdev, plist,
999
8.82k
                &(((tiffsep_device *)pdev)->devn_params),
1000
8.82k
                &(((tiffsep_device *)pdev)->equiv_cmyk_colors));
1001
8.82k
    if (code < 0)
1002
0
        return code;
1003
1004
8.82k
    if ((code = param_write_bool(plist, "NoSeparationFiles", &pdevn->NoSeparationFiles)) < 0)
1005
0
        ecode = code;
1006
8.82k
    if ((code = param_write_bool(plist, "BigEndian", &pdevn->BigEndian)) < 0)
1007
0
        ecode = code;
1008
8.82k
    if ((code = param_write_bool(plist, "TIFFDateTime", &pdevn->write_datetime)) < 0)
1009
0
        ecode = code;
1010
8.82k
    if ((code = tiff_compression_param_string(&comprstr, pdevn->Compression)) < 0 ||
1011
8.82k
        (code = param_write_string(plist, "Compression", &comprstr)) < 0)
1012
0
        ecode = code;
1013
8.82k
    if ((code = param_write_long(plist, "MaxStripSize", &pdevn->MaxStripSize)) < 0)
1014
0
        ecode = code;
1015
8.82k
    if ((code = param_write_long(plist, "BitsPerComponent", &pdevn->BitsPerComponent)) < 0)
1016
0
        ecode = code;
1017
8.82k
    if ((code = param_write_int(plist, "MaxSpots", &pdevn->max_spots)) < 0)
1018
0
        ecode = code;
1019
8.82k
    if ((code = param_write_bool(plist, "LockColorants", &pdevn->lock_colorants)) < 0)
1020
0
        ecode = code;
1021
8.82k
    if ((code = param_write_bool(plist, "PrintSpotCMYK", &pdevn->PrintSpotCMYK)) < 0)
1022
0
        ecode = code;
1023
8.82k
    if ((code = gx_downscaler_write_params(plist, &pdevn->downscale,
1024
8.82k
                                           GX_DOWNSCALER_PARAMS_MFS |
1025
8.82k
                                           GX_DOWNSCALER_PARAMS_TRAP)) < 0)
1026
0
        ecode = code;
1027
1028
8.82k
    return ecode;
1029
8.82k
}
1030
1031
/* Set parameters.  We allow setting the number of bits per component. */
1032
static int
1033
tiffsep_put_params(gx_device * pdev, gs_param_list * plist)
1034
2.30k
{
1035
2.30k
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1036
2.30k
    int code;
1037
2.30k
    const char *param_name;
1038
2.30k
    gs_param_string comprstr;
1039
2.30k
    long bpc = pdevn->BitsPerComponent;
1040
2.30k
    int max_spots = pdevn->max_spots;
1041
1042
2.30k
    switch (code = param_read_bool(plist, (param_name = "NoSeparationFiles"),
1043
2.30k
        &pdevn->NoSeparationFiles)) {
1044
0
    default:
1045
0
        param_signal_error(plist, param_name, code);
1046
0
        return code;
1047
227
    case 0:
1048
2.30k
    case 1:
1049
2.30k
        break;
1050
2.30k
    }
1051
    /* Read BigEndian option as bool */
1052
2.30k
    switch (code = param_read_bool(plist, (param_name = "BigEndian"), &pdevn->BigEndian)) {
1053
0
        default:
1054
0
            param_signal_error(plist, param_name, code);
1055
0
            return code;
1056
227
        case 0:
1057
2.30k
        case 1:
1058
2.30k
            break;
1059
2.30k
    }
1060
2.30k
    switch (code = param_read_bool(plist, (param_name = "TIFFDateTime"), &pdevn->write_datetime)) {
1061
0
        default:
1062
0
            param_signal_error(plist, param_name, code);
1063
227
        case 0:
1064
2.30k
        case 1:
1065
2.30k
            break;
1066
2.30k
    }
1067
2.30k
    switch (code = param_read_bool(plist, (param_name = "PrintSpotCMYK"), &pdevn->PrintSpotCMYK)) {
1068
0
        default:
1069
0
            param_signal_error(plist, param_name, code);
1070
0
            return code;
1071
227
        case 0:
1072
2.30k
        case 1:
1073
2.30k
            break;
1074
2.30k
    }
1075
1076
2.30k
    switch (code = param_read_long(plist, (param_name = "BitsPerComponent"), &bpc)) {
1077
227
        case 0:
1078
227
            if ((bpc == 1) || (bpc == 8)) {
1079
227
                pdevn->BitsPerComponent = bpc;
1080
227
                break;
1081
227
            }
1082
0
            code = gs_error_rangecheck;
1083
0
        default:
1084
0
            param_signal_error(plist, param_name, code);
1085
0
            return code;
1086
2.07k
        case 1:
1087
2.07k
            break;
1088
2.30k
    }
1089
1090
    /* Read Compression */
1091
2.30k
    switch (code = param_read_string(plist, (param_name = "Compression"), &comprstr)) {
1092
227
        case 0:
1093
227
            if ((code = tiff_compression_id(&pdevn->Compression, &comprstr)) < 0) {
1094
1095
0
                errprintf(pdevn->memory, "Unknown compression setting\n");
1096
1097
0
                param_signal_error(plist, param_name, code);
1098
0
                return code;
1099
0
            }
1100
227
            if (!tiff_compression_allowed(pdevn->Compression, bpc)) {
1101
0
                errprintf(pdevn->memory, "Invalid compression setting for this bitdepth\n");
1102
1103
0
                param_signal_error(plist, param_name, gs_error_rangecheck);
1104
0
                return_error(gs_error_rangecheck);
1105
0
            }
1106
227
            break;
1107
2.07k
        case 1:
1108
2.07k
            break;
1109
0
        default:
1110
0
            param_signal_error(plist, param_name, code);
1111
0
            return code;
1112
2.30k
    }
1113
2.30k
    switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &pdevn->MaxStripSize)) {
1114
227
        case 0:
1115
            /*
1116
             * Strip must be large enough to accommodate a raster line.
1117
             * If the max strip size is too small, we still write a single
1118
             * line per strip rather than giving an error.
1119
             */
1120
227
            if (pdevn->MaxStripSize >= 0)
1121
227
                break;
1122
0
            code = gs_error_rangecheck;
1123
0
        default:
1124
0
            param_signal_error(plist, param_name, code);
1125
0
            return code;
1126
2.07k
        case 1:
1127
2.07k
            break;
1128
2.30k
    }
1129
2.30k
    switch (code = param_read_bool(plist, (param_name = "LockColorants"),
1130
2.30k
            &(pdevn->lock_colorants))) {
1131
227
        case 0:
1132
227
            break;
1133
2.07k
        case 1:
1134
2.07k
            break;
1135
0
        default:
1136
0
            param_signal_error(plist, param_name, code);
1137
0
            return code;
1138
2.30k
    }
1139
2.30k
    switch (code = param_read_int(plist, (param_name = "MaxSpots"), &max_spots)) {
1140
227
        case 0:
1141
227
            if ((max_spots >= 0) && (max_spots <= GS_CLIENT_COLOR_MAX_COMPONENTS-4)) {
1142
227
                pdevn->max_spots = max_spots;
1143
227
                break;
1144
227
            }
1145
0
            emprintf1(pdev->memory, "MaxSpots must be between 0 and %d\n",
1146
0
                      GS_CLIENT_COLOR_MAX_COMPONENTS-4);
1147
0
            return_error(gs_error_rangecheck);
1148
2.07k
        case 1:
1149
2.07k
            break;
1150
0
        default:
1151
0
            param_signal_error(plist, param_name, code);
1152
0
            return code;
1153
2.30k
    }
1154
1155
2.30k
    code = gx_downscaler_read_params(plist, &pdevn->downscale,
1156
2.30k
                                     GX_DOWNSCALER_PARAMS_MFS | GX_DOWNSCALER_PARAMS_TRAP);
1157
2.30k
    if (code < 0)
1158
0
        return code;
1159
1160
2.30k
    code = devn_printer_put_params(pdev, plist,
1161
2.30k
                &(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
1162
1163
2.30k
    return(code);
1164
2.30k
}
1165
1166
static void build_comp_to_sep_map(tiffsep_device *, short *);
1167
static int number_output_separations(int, int, int, int);
1168
static int create_separation_file_name(tiffsep_device *, char *, uint, int, bool);
1169
1170
/* Open the tiffsep1 device.  This will now be using planar buffers so that
1171
   we are not limited to 64 bit chunky */
1172
int
1173
tiffsep1_prn_open(gx_device * pdev)
1174
765
{
1175
765
    gx_device_printer *ppdev = (gx_device_printer *)pdev;
1176
765
    tiffsep1_device *pdev_sep = (tiffsep1_device *) pdev;
1177
765
    int code, k;
1178
1179
    /* Use our own warning and error message handlers in libtiff */
1180
765
    tiff_set_handlers();
1181
1182
    /* With planar the depth can be more than 64.  Update the color
1183
       info to reflect the proper depth and number of planes */
1184
765
    pdev_sep->warning_given = false;
1185
765
    if (pdev_sep->devn_params.page_spot_colors >= 0) {
1186
230
        pdev->color_info.num_components =
1187
230
            (pdev_sep->devn_params.page_spot_colors
1188
230
                                 + pdev_sep->devn_params.num_std_colorant_names);
1189
230
        if (pdev->color_info.num_components > pdev->color_info.max_components)
1190
0
            pdev->color_info.num_components = pdev->color_info.max_components;
1191
535
    } else {
1192
        /* We do not know how many spots may occur on the page.
1193
           For this reason we go ahead and allocate the maximum that we
1194
           have available.  Note, lack of knowledge only occurs in the case
1195
           of PS files.  With PDF we know a priori the number of spot
1196
           colorants.  */
1197
535
        int num_comp = pdev_sep->max_spots + 4; /* Spots + CMYK */
1198
535
        if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS)
1199
0
            num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS;
1200
535
        pdev->color_info.num_components = num_comp;
1201
535
        pdev->color_info.max_components = num_comp;
1202
535
    }
1203
    /* Push this to the max amount as a default if someone has not set it */
1204
765
    if (pdev_sep->devn_params.num_separation_order_names == 0)
1205
49.7k
        for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
1206
48.9k
            pdev_sep->devn_params.separation_order_map[k] = k;
1207
48.9k
        }
1208
765
    pdev->color_info.depth = bpc_to_depth(pdev->color_info.num_components,
1209
765
                                          pdev_sep->devn_params.bitspercomponent);
1210
765
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1211
765
    code = gdev_prn_open_planar(pdev, true);
1212
765
    while (pdev->child)
1213
0
        pdev = pdev->child;
1214
765
    ppdev = (gx_device_printer *)pdev;
1215
765
    pdev_sep = (tiffsep1_device *)pdev;
1216
1217
765
    ppdev->file = NULL;
1218
765
    pdev->icc_struct->supports_devn = true;
1219
1220
765
    return code;
1221
765
}
1222
1223
/* Close the tiffsep device */
1224
int
1225
tiffsep1_prn_close(gx_device * pdev)
1226
765
{
1227
765
    tiffsep1_device * const tfdev = (tiffsep1_device *) pdev;
1228
765
    char *name= NULL;
1229
765
    int code = gdev_prn_close(pdev);
1230
765
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1231
765
    int comp_num;
1232
765
    const char *fmt;
1233
765
    gs_parsed_file_name_t parsed;
1234
1235
765
    if (code < 0)
1236
0
        return code;
1237
1238
765
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
1239
765
                                     strlen(tfdev->fname), pdev->memory);
1240
765
    if (code < 0) {
1241
0
        goto done;
1242
0
    }
1243
1244
765
#ifndef PPM_COMBINED_OUTPUT /* Only delete the default file if it isn't our pppraw output */
1245
    /* If we are doing separate pages, delete the old default file */
1246
765
    if (parsed.iodev == iodev_default(pdev->memory)) {          /* filename includes "%nnd" */
1247
765
        char *compname = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_prn_close(compname)");
1248
765
        if (!compname) {
1249
0
            code = gs_note_error(gs_error_VMerror);
1250
0
            goto done;
1251
0
        }
1252
1253
765
        if (fmt) {
1254
0
            long count1 = pdev->PageCount;
1255
1256
0
            while (*fmt != 'l' && *fmt != '%')
1257
0
                --fmt;
1258
0
            if (*fmt == 'l')
1259
0
                gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, count1);
1260
0
            else
1261
0
                gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, (int)count1);
1262
0
            parsed.iodev->procs.delete_file(parsed.iodev, compname);
1263
765
        } else {
1264
765
            parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname);
1265
765
        }
1266
765
        gs_free_object(pdev->memory, compname, "tiffsep1_prn_close(compname)");
1267
765
    }
1268
765
#endif
1269
1270
765
    build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
1271
    /* Close the separation files */
1272
2.60k
    for (comp_num = 0; comp_num < tfdev->page_num_comps; comp_num++ ) {
1273
1.84k
        const char *lname_empty = "";
1274
1.84k
        char *lname = NULL;
1275
1276
1.84k
        if (tfdev->tiff[comp_num] != NULL) {
1277
914
            tiff_filename_from_tiff(tfdev->tiff[comp_num], &name);
1278
914
        }
1279
929
        else {
1280
929
            name = (char *)lname_empty;
1281
929
        }
1282
1283
1.84k
        lname = (char *)gs_alloc_bytes(tfdev->memory, strlen(name) + 1, "tiffsep1_prn_close");
1284
1.84k
        if (lname == NULL) {
1285
0
            code = gs_note_error(gs_error_VMerror);
1286
0
            goto done;
1287
0
        }
1288
1.84k
        memcpy(lname, name, strlen(name) + 1);
1289
1290
1.84k
        if (tfdev->tiff[comp_num]) {
1291
914
            void *t = TIFFClientdata(tfdev->tiff[comp_num]);
1292
1293
914
            TIFFCleanup(tfdev->tiff[comp_num]);
1294
914
            gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep1_prn_close");
1295
914
            tfdev->tiff[comp_num] = NULL;
1296
914
        }
1297
1.84k
        if (tfdev->sep_file[comp_num] != NULL) {
1298
914
            code = gx_device_close_output_file(pdev, lname, tfdev->sep_file[comp_num]);
1299
914
            if (code >= 0)
1300
914
                code = gs_remove_outputfile_control_path(pdev->memory, lname);
1301
914
            if (code < 0) {
1302
0
                goto done;
1303
0
            }
1304
914
            tfdev->sep_file[comp_num] = NULL;
1305
914
        }
1306
1.84k
        gs_free_object(tfdev->memory, lname, "tiffsep1_prn_close");
1307
1.84k
    }
1308
1309
765
done:
1310
765
    return code;
1311
765
}
1312
1313
/*
1314
 * This routine will check to see if the color component name  match those
1315
 * that are available amoung the current device's color components.
1316
 *
1317
 * Parameters:
1318
 *   dev - pointer to device data structure.
1319
 *   pname - pointer to name (zero termination not required)
1320
 *   nlength - length of the name
1321
 *
1322
 * This routine returns a positive value (0 to n) which is the device colorant
1323
 * number if the name is found.  It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
1324
 * the colorant is not being used due to a SeparationOrder device parameter.
1325
 * It returns a negative value if not found.
1326
 */
1327
static int
1328
tiffsep_get_color_comp_index(gx_device * dev, const char * pname,
1329
                                int name_size, int component_type)
1330
143k
{
1331
143k
    tiffsep_device * pdev = (tiffsep_device *) dev;
1332
143k
    int index;
1333
1334
143k
    if (strncmp(pname, "None", name_size) == 0) return -1;
1335
143k
    index = devn_get_color_comp_index(dev,
1336
143k
                &(pdev->devn_params), &(pdev->equiv_cmyk_colors),
1337
143k
                pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS);
1338
    /* This is a one shot deal.  That is it will simply post a notice once that
1339
       some colorants will be converted due to a limit being reached.  It will
1340
       not list names of colorants since then I would need to keep track of
1341
       which ones I have already mentioned.  Also, if someone is fooling with
1342
       num_order, then this warning is not given since they should know what
1343
       is going on already */
1344
143k
    if (index < 0 && component_type == SEPARATION_NAME &&
1345
143k
        pdev->warning_given == false &&
1346
143k
        pdev->devn_params.num_separation_order_names == 0) {
1347
0
        dmlprintf(dev->memory, "**** Max spot colorants reached.\n");
1348
0
        dmlprintf(dev->memory, "**** Some colorants will be converted to equivalent CMYK values.\n");
1349
0
        dmlprintf(dev->memory, "**** If this is a Postscript file, try using the -dMaxSpots= option.\n");
1350
0
        pdev->warning_given = true;
1351
0
    }
1352
143k
    return index;
1353
143k
}
1354
1355
/*
1356
 * There can be a conflict if a separation name is used as part of the file
1357
 * name for a separation output file.  PostScript and PDF do not restrict
1358
 * the characters inside separation names.  However most operating systems
1359
 * have some sort of restrictions.  For instance: /, \, and : have special
1360
 * meaning under Windows.  This implies that there should be some sort of
1361
 * escape sequence for special characters.  This routine exists as a place
1362
 * to put the handling of that escaping.  However it is not actually
1363
 * implemented. Instead we just map them to '_'.
1364
 */
1365
static void
1366
copy_separation_name(tiffsep_device * pdev,
1367
                char * buffer, int max_size, int sep_num, int escape)
1368
19
{
1369
19
    int sep_size = pdev->devn_params.separations.names[sep_num].size;
1370
19
    const byte *p = pdev->devn_params.separations.names[sep_num].data;
1371
19
    int r, w, use_sep_num = 0;
1372
19
    const char *stdnames[4] = {"CYAN", "MAGENTA", "YELLOW", "BLACK"};
1373
19
    char sep_num_str[16] = "";
1374
1375
    /* Previously the code here would simply replace any char that wasn't
1376
     * passed by gp_file_name_good_char (and %) with '_'. The grounds for
1377
     * gp_file_name_good_char are obvious enough. The reason for '%' is
1378
     * that the string gets fed to a printf style consumer later. It had
1379
     * problems in that any top bit set char was let through, which upset
1380
     * the file handling routines as they assume the filenames are in
1381
     * utf-8 format. */
1382
1383
95
    for (r=0;r<4;r++)
1384
76
    {
1385
76
        if (strlen(stdnames[r]) == pdev->devn_params.separations.names[sep_num].size) {
1386
0
            use_sep_num = 1;
1387
0
            for (w=0;w<strlen(stdnames[r]);w++) {
1388
0
                if (toupper(pdev->devn_params.separations.names[sep_num].data[w]) != stdnames[r][w]) {
1389
0
                    use_sep_num = 0;
1390
0
                    break;
1391
0
                }
1392
0
            }
1393
0
        }
1394
76
    }
1395
19
    if (use_sep_num != 0)
1396
0
        gs_snprintf(sep_num_str, sizeof(sep_num_str), "%d", sep_num);
1397
1398
    /* New code: Copy the name, escaping non gp_file_name_good_char chars,
1399
     * % and top bit set chars using %02x format. In addition, if 'escape'
1400
     * is set, output % as %% to allow for printf later.
1401
     */
1402
19
    r = 0;
1403
19
    w = 0;
1404
98
    while (r < sep_size && w < max_size-1 - strlen(sep_num_str))
1405
79
    {
1406
79
        int c = p[r++];
1407
79
        if (c >= 127 ||
1408
79
            !gp_file_name_good_char(c) ||
1409
79
            c == '%')
1410
0
        {
1411
            /* Top bit set, backspace, or char we can't represent on the
1412
             * filesystem. */
1413
0
            if (w + 2 + escape >= max_size-1 - strlen(sep_num_str))
1414
0
                break;
1415
0
            buffer[w++] = '%';
1416
0
            if (escape)
1417
0
                buffer[w++] = '%';
1418
0
            buffer[w++] = "0123456789ABCDEF"[c>>4];
1419
0
            buffer[w++] = "0123456789ABCDEF"[c&15];
1420
0
        }
1421
79
        else
1422
79
        {
1423
79
            buffer[w++] = c;
1424
79
        }
1425
79
    }
1426
19
    if (use_sep_num) {
1427
0
        for (r = 0;r < strlen(sep_num_str);r++)
1428
0
            buffer[w++] = sep_num_str[r];
1429
0
    }
1430
19
    buffer[w] = 0;       /* Terminate string */
1431
19
}
1432
1433
/*
1434
 * Determine the length of the base file name.  If the file name includes
1435
 * the extension '.tif', then we remove it from the length of the file
1436
 * name.
1437
 */
1438
static int
1439
length_base_file_name(tiffsep_device * pdev, bool *double_f)
1440
1.51k
{
1441
1.51k
    int base_filename_length = strlen(pdev->fname);
1442
1443
1.51k
#define REMOVE_TIF_FROM_BASENAME 1
1444
1.51k
#if REMOVE_TIF_FROM_BASENAME
1445
1.51k
    if (base_filename_length > 4 &&
1446
1.51k
        pdev->fname[base_filename_length - 4] == '.'  &&
1447
1.51k
        toupper(pdev->fname[base_filename_length - 3]) == 'T'  &&
1448
1.51k
        toupper(pdev->fname[base_filename_length - 2]) == 'I'  &&
1449
1.51k
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1450
0
        base_filename_length -= 4;
1451
0
        *double_f = false;
1452
0
    }
1453
1.51k
    else if (base_filename_length > 5 &&
1454
1.51k
        pdev->fname[base_filename_length - 5] == '.'  &&
1455
1.51k
        toupper(pdev->fname[base_filename_length - 4]) == 'T'  &&
1456
1.51k
        toupper(pdev->fname[base_filename_length - 3]) == 'I'  &&
1457
1.51k
        toupper(pdev->fname[base_filename_length - 2]) == 'F'  &&
1458
1.51k
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1459
1.51k
        base_filename_length -= 5;
1460
1.51k
        *double_f = true;
1461
1.51k
    }
1462
1.51k
#endif
1463
1.51k
#undef REMOVE_TIF_FROM_BASENAME
1464
1465
1.51k
    return base_filename_length;
1466
1.51k
}
1467
1468
/*
1469
 * Create a name for a separation file.
1470
 */
1471
static int
1472
create_separation_file_name(tiffsep_device * pdev, char * buffer,
1473
                                uint max_size, int sep_num, bool use_sep_name)
1474
914
{
1475
914
    bool double_f = false;
1476
914
    uint base_filename_length = length_base_file_name(pdev, &double_f);
1477
1478
    /*
1479
     * In most cases it is more convenient if we append '.tif' to the end
1480
     * of the file name.
1481
     */
1482
933
#define APPEND_TIF_TO_NAME 1
1483
933
#define SUFFIX_SIZE (4 * APPEND_TIF_TO_NAME)
1484
1485
914
    memcpy(buffer, pdev->fname, base_filename_length);
1486
914
    buffer[base_filename_length++] = use_sep_name ? '(' : '.';
1487
914
    buffer[base_filename_length] = 0;  /* terminate the string */
1488
1489
914
    if (sep_num < pdev->devn_params.num_std_colorant_names) {
1490
908
        if (max_size < strlen(pdev->devn_params.std_colorant_names[sep_num]))
1491
0
            return_error(gs_error_rangecheck);
1492
908
        strcat(buffer, pdev->devn_params.std_colorant_names[sep_num]);
1493
908
    }
1494
6
    else {
1495
6
        sep_num -= pdev->devn_params.num_std_colorant_names;
1496
6
        if (use_sep_name) {
1497
6
            copy_separation_name(pdev, buffer + base_filename_length,
1498
6
                                max_size - SUFFIX_SIZE - 2, sep_num, 1);
1499
6
        } else {
1500
                /* Max of 10 chars in %d format */
1501
0
            if (max_size < base_filename_length + 11)
1502
0
                return_error(gs_error_rangecheck);
1503
0
            gs_snprintf(buffer + base_filename_length, max_size - base_filename_length, "s%d", sep_num);
1504
0
        }
1505
6
    }
1506
914
    if (use_sep_name)
1507
914
        strcat(buffer, ")");
1508
1509
914
#if APPEND_TIF_TO_NAME
1510
914
    if (double_f) {
1511
914
        if (max_size < strlen(buffer) + SUFFIX_SIZE + 1)
1512
0
            return_error(gs_error_rangecheck);
1513
914
        strcat(buffer, ".tiff");
1514
914
    }
1515
0
    else {
1516
0
        if (max_size < strlen(buffer) + SUFFIX_SIZE)
1517
0
            return_error(gs_error_rangecheck);
1518
0
        strcat(buffer, ".tif");
1519
0
    }
1520
914
#endif
1521
914
    return 0;
1522
914
}
1523
1524
/*
1525
 * Determine the number of output separations for the tiffsep device.
1526
 *
1527
 * There are several factors which affect the number of output separations
1528
 * for the tiffsep device.
1529
 *
1530
 * Due to limitations on the size of a gx_color_index, we are limited to a
1531
 * maximum of 8 colors per pass.  Thus the tiffsep device is set to 8
1532
 * components.  However this is not usually the number of actual separation
1533
 * files to be created.
1534
 *
1535
 * If the SeparationOrder parameter has been specified, then we use it to
1536
 * select the number and which separation files are created.
1537
 *
1538
 * If the SeparationOrder parameter has not been specified, then we use the
1539
 * nuber of process colors (CMYK) and the number of spot colors unless we
1540
 * exceed the 8 component maximum for the device.
1541
 *
1542
 * Note:  Unlike most other devices, the tiffsep device will accept more than
1543
 * four spot colors.  However the extra spot colors will not be imaged
1544
 * unless they are selected by the SeparationOrder parameter.  (This does
1545
 * allow the user to create more than 8 separations by a making multiple
1546
 * passes and using the SeparationOrder parameter.)
1547
*/
1548
static int
1549
number_output_separations(int num_dev_comp, int num_std_colorants,
1550
                                        int num_order, int num_spot)
1551
227
{
1552
227
    int num_comp =  num_std_colorants + num_spot;
1553
1554
227
    if (num_comp > num_dev_comp)
1555
0
        num_comp = num_dev_comp;
1556
227
    if (num_order)
1557
0
        num_comp = num_order;
1558
227
    return num_comp;
1559
227
}
1560
1561
/*
1562
 * This routine creates a list to map the component number to a separation number.
1563
 * Values less than 4 refer to the CMYK colorants.  Higher values refer to a
1564
 * separation number.
1565
 *
1566
 * This is the inverse of the separation_order_map.
1567
 */
1568
static void
1569
build_comp_to_sep_map(tiffsep_device * pdev, short * map_comp_to_sep)
1570
1.36k
{
1571
1.36k
    int num_sep = pdev->devn_params.separations.num_separations;
1572
1.36k
    int num_std_colorants = pdev->devn_params.num_std_colorant_names;
1573
1.36k
    int sep_num;
1574
1.36k
    int num_channels;
1575
1576
    /* since both proc colors and spot colors are packed in same encoded value we
1577
       need to have this limit */
1578
1579
1.36k
    num_channels =
1580
1.36k
        ( (num_std_colorants + num_sep) < (GX_DEVICE_COLOR_MAX_COMPONENTS) ? (num_std_colorants + num_sep) : (GX_DEVICE_COLOR_MAX_COMPONENTS) );
1581
1582
6.82k
    for (sep_num = 0; sep_num < num_channels; sep_num++) {
1583
5.46k
        int comp_num = pdev->devn_params.separation_order_map[sep_num];
1584
1585
5.46k
        if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
1586
5.46k
            map_comp_to_sep[comp_num] = sep_num;
1587
5.46k
    }
1588
1.36k
}
1589
1590
/* Open the tiffsep device.  This will now be using planar buffers so that
1591
   we are not limited to 64 bit chunky */
1592
int
1593
tiffsep_prn_open(gx_device * pdev)
1594
0
{
1595
0
    gx_device_printer *ppdev = (gx_device_printer *)pdev;
1596
0
    tiffsep_device *pdev_sep = (tiffsep_device *) pdev;
1597
0
    int code, k;
1598
0
    cmm_dev_profile_t *profile_struct;
1599
1600
    /* Use our own warning and error message handlers in libtiff */
1601
0
    tiff_set_handlers();
1602
1603
0
    code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct);
1604
0
    if (code < 0)
1605
0
        return code;
1606
1607
    /* For the planar device we need to set up the bit depth of each plane.
1608
       For other devices this is handled in check_device_separable where
1609
       we compute the bit shift for the components etc. */
1610
0
    for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
1611
0
        pdev->color_info.comp_bits[k] = 8;
1612
0
    }
1613
1614
    /* With planar the depth can be more than 64.  Update the color
1615
       info to reflect the proper depth and number of planes */
1616
0
    pdev_sep->warning_given = false;
1617
0
    if (pdev_sep->devn_params.page_spot_colors >= 0) {
1618
1619
        /* PDF case, as the page spot colors are known. */
1620
0
        if (profile_struct->spotnames != NULL) {
1621
1622
            /* PDF case, NCLR ICC profile with spot names. The ICC spots
1623
               will use up some of the max_spots values. If max_spots is
1624
               too small to accomodate even the ICC spots, throw an error */
1625
0
            if (profile_struct->spotnames->count - 4 > pdev_sep->max_spots ||
1626
0
                profile_struct->spotnames->count < 4 ||
1627
0
                profile_struct->spotnames->count <
1628
0
                profile_struct->device_profile[0]->num_comps) {
1629
0
                gs_warn("ICC profile colorant names count error");
1630
0
                return_error(gs_error_rangecheck);
1631
0
            }
1632
0
            pdev->color_info.num_components =
1633
0
                (profile_struct->spotnames->count
1634
0
                    + pdev_sep->devn_params.page_spot_colors);
1635
0
            if (pdev->color_info.num_components > pdev->color_info.max_components)
1636
0
                pdev->color_info.num_components = pdev->color_info.max_components;
1637
0
        } else {
1638
1639
            /* Use the information that is in the page spot color. We should
1640
               be here if we are processing a PDF and we do not have a DeviceN
1641
               ICC profile specified for output */
1642
0
            if (!(pdev_sep->lock_colorants)) {
1643
0
                pdev->color_info.num_components =
1644
0
                    (pdev_sep->devn_params.page_spot_colors
1645
0
                    + pdev_sep->devn_params.num_std_colorant_names);
1646
0
                if (pdev->color_info.num_components > pdev->color_info.max_components)
1647
0
                    pdev->color_info.num_components = pdev->color_info.max_components;
1648
0
            }
1649
0
        }
1650
0
    } else {
1651
        /* We do not know how many spots may occur on the page.
1652
           For this reason we go ahead and allocate the maximum that we
1653
           have available.  Note, lack of knowledge only occurs in the case
1654
           of PS files. With PDF we know a priori the number of spot
1655
           colorants. However, the first time the device is opened,
1656
           pdev_sep->devn_params.page_spot_colors is -1 even if we are
1657
           dealing with a PDF file, so we will first find ourselves here,
1658
           which will set num_comp based upon max_spots + 4. If -dMaxSpots
1659
           was set (Default is GS_SOFT_MAX_SPOTS which is 10) ,
1660
           it is made use of here. */
1661
0
        if (!(pdev_sep->lock_colorants)) {
1662
0
            int num_comp = pdev_sep->max_spots + 4; /* Spots + CMYK */
1663
0
            if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS)
1664
0
                num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS;
1665
0
            pdev->color_info.num_components = num_comp;
1666
0
            pdev->color_info.max_components = num_comp;
1667
0
        }
1668
0
    }
1669
    /* Push this to the max amount as a default if someone has not set it */
1670
0
    if (pdev_sep->devn_params.num_separation_order_names == 0)
1671
0
        for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
1672
0
            pdev_sep->devn_params.separation_order_map[k] = k;
1673
0
        }
1674
0
    pdev->color_info.depth = pdev->color_info.num_components *
1675
0
                             pdev_sep->devn_params.bitspercomponent;
1676
0
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1677
0
    code = gdev_prn_open_planar(pdev, true);
1678
0
    if (code < 0)
1679
0
        return code;
1680
0
    while (pdev->child)
1681
0
        pdev = pdev->child;
1682
0
    ppdev = (gx_device_printer *)pdev;
1683
1684
0
    ppdev->file = NULL;
1685
0
    pdev->icc_struct->supports_devn = true;
1686
1687
    /* Set up the icc link settings at this time.  Only CMYK post render profiles
1688
       are allowed */
1689
0
    return gx_downscaler_create_post_render_link((gx_device *)pdev,
1690
0
                                                 &pdev_sep->icclink);
1691
0
}
1692
1693
static int
1694
tiffsep_close_sep_file(tiffsep_device *tfdev, const char *fn, int comp_num)
1695
0
{
1696
0
    int code;
1697
1698
0
    if (tfdev->tiff[comp_num]) {
1699
0
        TIFFClose(tfdev->tiff[comp_num]);
1700
0
        tfdev->tiff[comp_num] = NULL;
1701
0
    }
1702
1703
0
    code = gx_device_close_output_file((gx_device *)tfdev,
1704
0
                                       fn,
1705
0
                                       tfdev->sep_file[comp_num]);
1706
0
    tfdev->sep_file[comp_num] = NULL;
1707
0
    tfdev->tiff[comp_num] = NULL;
1708
1709
0
    return code;
1710
0
}
1711
1712
static int
1713
tiffsep_close_comp_file(tiffsep_device *tfdev, const char *fn)
1714
0
{
1715
0
    int code;
1716
1717
0
    if (tfdev->tiff_comp) {
1718
0
        TIFFClose(tfdev->tiff_comp);
1719
0
        tfdev->tiff_comp = NULL;
1720
0
    }
1721
1722
0
    code = gx_device_close_output_file((gx_device *)tfdev,
1723
0
                                       fn,
1724
0
                                       tfdev->comp_file);
1725
0
    tfdev->comp_file = NULL;
1726
1727
0
    return code;
1728
0
}
1729
1730
/* Close the tiffsep device */
1731
int
1732
tiffsep_prn_close(gx_device * pdev)
1733
0
{
1734
0
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1735
0
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1736
0
    char *name = NULL;
1737
0
    int code;
1738
0
    int comp_num;
1739
1740
0
    gsicc_free_link_dev(pdevn->icclink);
1741
0
    pdevn->icclink = NULL;
1742
1743
0
    if (pdevn->tiff_comp) {
1744
0
        void *t = TIFFClientdata(pdevn->tiff_comp);
1745
0
        TIFFCleanup(pdevn->tiff_comp);
1746
0
        gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep_prn_close");
1747
0
        pdevn->tiff_comp = NULL;
1748
0
    }
1749
0
    code = gdev_prn_close(pdev);
1750
0
    if (code < 0) {
1751
0
        goto done;
1752
0
    }
1753
1754
0
    build_comp_to_sep_map(pdevn, map_comp_to_sep);
1755
    /* Close the separation files */
1756
0
    for (comp_num = 0; comp_num < pdevn->page_num_comps; comp_num++ ) {
1757
0
        const char *lname_empty = "";
1758
0
        char *lname = NULL;
1759
1760
0
        if (pdevn->tiff[comp_num] != NULL) {
1761
0
            tiff_filename_from_tiff(pdevn->tiff[comp_num], &name);
1762
0
        }
1763
0
        else {
1764
0
            name = (char *)lname_empty;
1765
0
        }
1766
1767
0
        lname = (char *)gs_alloc_bytes(pdevn->memory, strlen(name) + 1, "tiffsep1_prn_close");
1768
0
        if (lname == NULL) {
1769
0
            code = gs_note_error(gs_error_VMerror);
1770
0
            goto done;
1771
0
        }
1772
0
        memcpy(lname, name, strlen(name) + 1);
1773
1774
0
        if (pdevn->tiff[comp_num]) {
1775
0
            void *t = TIFFClientdata(pdevn->tiff[comp_num]);
1776
0
            TIFFCleanup(pdevn->tiff[comp_num]);
1777
0
            gs_free(pdevn->memory, t, sizeof(tifs_io_private), 1, "tiffsep_prn_close");
1778
0
            pdevn->tiff[comp_num] = NULL;
1779
0
        }
1780
1781
0
        if (pdevn->sep_file[comp_num]) {
1782
0
            code = gx_device_close_output_file((gx_device *)pdevn, lname, pdevn->sep_file[comp_num]);
1783
0
            if (code >= 0)
1784
0
                code = gs_remove_outputfile_control_path(pdevn->memory, lname);
1785
0
            if (code < 0) {
1786
0
                goto done;
1787
0
            }
1788
0
            pdevn->sep_file[comp_num] = NULL;
1789
0
        }
1790
0
        gs_free_object(pdevn->memory, lname, "tiffsep1_prn_close");
1791
0
    }
1792
1793
0
done:
1794
0
    return code;
1795
0
}
1796
1797
/*
1798
 * Build a CMYK equivalent to a raster line from planar buffer
1799
 */
1800
static void
1801
build_cmyk_raster_line_fromplanar(gs_get_bits_params_t *params, byte * dest,
1802
                                  int width, int num_comp,
1803
                                  cmyk_composite_map * cmyk_map, int num_order,
1804
                                  tiffsep_device * const tfdev)
1805
0
{
1806
0
    int pixel, comp_num;
1807
0
    uint temp, cyan, magenta, yellow, black;
1808
0
    cmyk_composite_map * cmyk_map_entry;
1809
0
    byte *start = dest;
1810
1811
0
    for (pixel = 0; pixel < width; pixel++) {
1812
0
        cmyk_map_entry = cmyk_map;
1813
0
        temp = *(params->data[tfdev->devn_params.separation_order_map[0]] + pixel);
1814
0
        cyan = cmyk_map_entry->c * temp;
1815
0
        magenta = cmyk_map_entry->m * temp;
1816
0
        yellow = cmyk_map_entry->y * temp;
1817
0
        black = cmyk_map_entry->k * temp;
1818
0
        cmyk_map_entry++;
1819
0
        for (comp_num = 1; comp_num < num_comp; comp_num++) {
1820
0
            temp =
1821
0
                *(params->data[tfdev->devn_params.separation_order_map[comp_num]] + pixel);
1822
0
            cyan += cmyk_map_entry->c * temp;
1823
0
            magenta += cmyk_map_entry->m * temp;
1824
0
            yellow += cmyk_map_entry->y * temp;
1825
0
            black += cmyk_map_entry->k * temp;
1826
0
            cmyk_map_entry++;
1827
0
        }
1828
0
        cyan /= frac_1;
1829
0
        magenta /= frac_1;
1830
0
        yellow /= frac_1;
1831
0
        black /= frac_1;
1832
0
        if (cyan > MAX_COLOR_VALUE)
1833
0
            cyan = MAX_COLOR_VALUE;
1834
0
        if (magenta > MAX_COLOR_VALUE)
1835
0
            magenta = MAX_COLOR_VALUE;
1836
0
        if (yellow > MAX_COLOR_VALUE)
1837
0
            yellow = MAX_COLOR_VALUE;
1838
0
        if (black > MAX_COLOR_VALUE)
1839
0
            black = MAX_COLOR_VALUE;
1840
0
        *dest++ = cyan;
1841
0
        *dest++ = magenta;
1842
0
        *dest++ = yellow;
1843
0
        *dest++ = black;
1844
0
    }
1845
    /* And now apply the post rendering profile to the scan line if it exists.
1846
       In place conversion */
1847
0
    if (tfdev->icclink != NULL) {
1848
0
        gsicc_bufferdesc_t buffer_desc;
1849
1850
0
        gsicc_init_buffer(&buffer_desc, tfdev->icclink->num_input, 1, false,
1851
0
            false, false, 0, width * 4, 1, width);
1852
0
        tfdev->icclink->procs.map_buffer(NULL, tfdev->icclink, &buffer_desc,
1853
0
            &buffer_desc, start, start);
1854
0
    }
1855
0
}
1856
1857
static void
1858
build_cmyk_raster_line_fromplanar_1bpc(gs_get_bits_params_t *params, byte * dest,
1859
                                       int width, int num_comp,
1860
                                       cmyk_composite_map * cmyk_map, int num_order,
1861
                                       tiffsep_device * const tfdev)
1862
0
{
1863
0
    int pixel, comp_num;
1864
0
    uint temp, cyan, magenta, yellow, black;
1865
0
    cmyk_composite_map * cmyk_map_entry;
1866
1867
0
    for (pixel = 0; pixel < width; pixel++) {
1868
0
        cmyk_map_entry = cmyk_map;
1869
0
        temp = *(params->data[tfdev->devn_params.separation_order_map[0]] + (pixel>>3));
1870
0
        temp = ((temp<<(pixel & 7))>>7) & 1;
1871
0
        cyan = cmyk_map_entry->c * temp;
1872
0
        magenta = cmyk_map_entry->m * temp;
1873
0
        yellow = cmyk_map_entry->y * temp;
1874
0
        black = cmyk_map_entry->k * temp;
1875
0
        cmyk_map_entry++;
1876
0
        for (comp_num = 1; comp_num < num_comp; comp_num++) {
1877
0
            temp =
1878
0
                *(params->data[tfdev->devn_params.separation_order_map[comp_num]] + (pixel>>3));
1879
0
            temp = ((temp<<(pixel & 7))>>7) & 1;
1880
0
            cyan += cmyk_map_entry->c * temp;
1881
0
            magenta += cmyk_map_entry->m * temp;
1882
0
            yellow += cmyk_map_entry->y * temp;
1883
0
            black += cmyk_map_entry->k * temp;
1884
0
            cmyk_map_entry++;
1885
0
        }
1886
0
        cyan /= frac_1;
1887
0
        magenta /= frac_1;
1888
0
        yellow /= frac_1;
1889
0
        black /= frac_1;
1890
0
        if (cyan > 1)
1891
0
            cyan = 1;
1892
0
        if (magenta > 1)
1893
0
            magenta = 1;
1894
0
        if (yellow > 1)
1895
0
            yellow = 1;
1896
0
        if (black > 1)
1897
0
            black = 1;
1898
0
        if ((pixel & 1) == 0)
1899
0
            *dest = (cyan<<7) | (magenta<<6) | (yellow<<5) | (black<<4);
1900
0
        else
1901
0
            *dest++ |= (cyan<<3) | (magenta<<2) | (yellow<<1) | black;
1902
0
    }
1903
0
}
1904
static void
1905
build_cmyk_raster_line_fromplanar_2bpc(gs_get_bits_params_t *params, byte * dest,
1906
                                       int width, int num_comp,
1907
                                       cmyk_composite_map * cmyk_map, int num_order,
1908
                                       tiffsep_device * const tfdev)
1909
0
{
1910
0
    int pixel, comp_num;
1911
0
    uint temp, cyan, magenta, yellow, black;
1912
0
    cmyk_composite_map * cmyk_map_entry;
1913
1914
0
    for (pixel = 0; pixel < width; pixel++) {
1915
0
        cmyk_map_entry = cmyk_map;
1916
0
        temp = *(params->data[tfdev->devn_params.separation_order_map[0]] + (pixel>>2));
1917
0
        temp = (((temp<<((pixel & 3)<<1))>>6) & 3) * 85;
1918
0
        cyan = cmyk_map_entry->c * temp;
1919
0
        magenta = cmyk_map_entry->m * temp;
1920
0
        yellow = cmyk_map_entry->y * temp;
1921
0
        black = cmyk_map_entry->k * temp;
1922
0
        cmyk_map_entry++;
1923
0
        for (comp_num = 1; comp_num < num_comp; comp_num++) {
1924
0
            temp =
1925
0
                *(params->data[tfdev->devn_params.separation_order_map[comp_num]] + (pixel>>2));
1926
0
            temp = (((temp<<((pixel & 3)<<1))>>6) & 3) * 85;
1927
0
            cyan += cmyk_map_entry->c * temp;
1928
0
            magenta += cmyk_map_entry->m * temp;
1929
0
            yellow += cmyk_map_entry->y * temp;
1930
0
            black += cmyk_map_entry->k * temp;
1931
0
            cmyk_map_entry++;
1932
0
        }
1933
0
        cyan /= frac_1;
1934
0
        magenta /= frac_1;
1935
0
        yellow /= frac_1;
1936
0
        black /= frac_1;
1937
0
        if (cyan > 3)
1938
0
            cyan = 3;
1939
0
        if (magenta > 3)
1940
0
            magenta = 3;
1941
0
        if (yellow > 3)
1942
0
            yellow = 3;
1943
0
        if (black > 3)
1944
0
            black = 3;
1945
0
        *dest++ = (cyan<<6) | (magenta<<4) | (yellow<<2) | black;
1946
0
    }
1947
0
}
1948
1949
static void
1950
build_cmyk_raster_line_fromplanar_4bpc(gs_get_bits_params_t *params, byte * dest,
1951
                                       int width, int num_comp,
1952
                                       cmyk_composite_map * cmyk_map, int num_order,
1953
                                       tiffsep_device * const tfdev)
1954
0
{
1955
0
    int pixel, comp_num;
1956
0
    uint temp, cyan, magenta, yellow, black;
1957
0
    cmyk_composite_map * cmyk_map_entry;
1958
1959
0
    for (pixel = 0; pixel < width; pixel++) {
1960
0
        cmyk_map_entry = cmyk_map;
1961
0
        temp = *(params->data[tfdev->devn_params.separation_order_map[0]] + (pixel>>1));
1962
0
        if (pixel & 1)
1963
0
            temp >>= 4;
1964
0
        temp &= 15;
1965
0
        cyan = cmyk_map_entry->c * temp;
1966
0
        magenta = cmyk_map_entry->m * temp;
1967
0
        yellow = cmyk_map_entry->y * temp;
1968
0
        black = cmyk_map_entry->k * temp;
1969
0
        cmyk_map_entry++;
1970
0
        for (comp_num = 1; comp_num < num_comp; comp_num++) {
1971
0
            temp =
1972
0
                *(params->data[tfdev->devn_params.separation_order_map[comp_num]] + (pixel>>1));
1973
0
            if (pixel & 1)
1974
0
                temp >>= 4;
1975
0
            temp &= 15;
1976
0
            cyan += cmyk_map_entry->c * temp;
1977
0
            magenta += cmyk_map_entry->m * temp;
1978
0
            yellow += cmyk_map_entry->y * temp;
1979
0
            black += cmyk_map_entry->k * temp;
1980
0
            cmyk_map_entry++;
1981
0
        }
1982
0
        cyan /= frac_1;
1983
0
        magenta /= frac_1;
1984
0
        yellow /= frac_1;
1985
0
        black /= frac_1;
1986
0
        if (cyan > 15)
1987
0
            cyan = 15;
1988
0
        if (magenta > 15)
1989
0
            magenta = 15;
1990
0
        if (yellow > 15)
1991
0
            yellow = 15;
1992
0
        if (black > 15)
1993
0
            black = 15;
1994
0
        *dest++ = (cyan<<4) | magenta;
1995
0
        *dest++ = (yellow<<4) | black;
1996
0
    }
1997
0
}
1998
1999
 /*
2000
 * This function prints out CMYK value with separation name for every
2001
 * separation. Where the original alternate colour space was DeviceCMYK, and the output
2002
 * ICC profile is CMYK, no transformation takes place. Where the original alternate space
2003
 * was not DeviceCMYK, the colour management system will be used to generate CMYK values
2004
 * from the original tint transform.
2005
 * NB if the output profile is DeviceN then we will use the DeviceCMYK profile to map the
2006
 * equivalents, *not* the DeviceN profile. This is a peculiar case.....
2007
 */
2008
static int
2009
print_cmyk_equivalent_colors(tiffsep_device *tfdev, int num_comp, cmyk_composite_map *cmyk_map)
2010
0
{
2011
0
    int comp_num;
2012
0
    char *name = (char *)gs_alloc_bytes(tfdev->memory, gp_file_name_sizeof,
2013
0
                                "tiffsep_print_cmyk_equivalent_colors(name)");
2014
2015
0
    if (!name) {
2016
0
        return_error(gs_error_VMerror);
2017
0
    }
2018
2019
0
    for (comp_num = 0; comp_num < num_comp; comp_num++) {
2020
0
        int sep_num = tfdev->devn_params.separation_order_map[comp_num];
2021
2022
0
        if (sep_num >= tfdev->devn_params.num_std_colorant_names) {
2023
0
            sep_num -= tfdev->devn_params.num_std_colorant_names;
2024
0
            if (gp_file_name_sizeof < tfdev->devn_params.separations.names[sep_num].size) {
2025
0
                if (name)
2026
0
                    gs_free_object(tfdev->memory, name, "tiffsep_print_cmyk_equivalent_colors(name)");
2027
0
                return_error(gs_error_rangecheck);
2028
0
            }
2029
0
            memcpy(name,
2030
0
                   (char *)tfdev->devn_params.separations.names[sep_num].data,
2031
0
                   tfdev->devn_params.separations.names[sep_num].size);
2032
0
            name[tfdev->devn_params.separations.names[sep_num].size] = '\0';
2033
0
            dmlprintf5(tfdev->memory, "%%%%SeparationColor: \"%s\" 100%% ink = %hd %hd %hd %hd CMYK\n",
2034
0
                       name,
2035
0
                       cmyk_map[comp_num].c,
2036
0
                       cmyk_map[comp_num].m,
2037
0
                       cmyk_map[comp_num].y,
2038
0
                       cmyk_map[comp_num].k);
2039
0
        }
2040
0
    }
2041
2042
0
    if (name) {
2043
0
        gs_free_object(tfdev->memory, name, "tiffsep_print_cmyk_equivalent_colors(name)");
2044
0
    }
2045
2046
0
    return 0;
2047
0
}
2048
2049
/*
2050
 * Output the image data for the tiff separation (tiffsep) device.  The data
2051
 * for the tiffsep device is written in separate planes to separate files.
2052
 *
2053
 * The DeviceN parameters (SeparationOrder, SeparationColorNames, and
2054
 * MaxSeparations) are applied to the tiffsep device.
2055
 */
2056
static int
2057
tiffsep_print_page(gx_device_printer * pdev, gp_file * file)
2058
0
{
2059
0
    tiffsep_device * const tfdev = (tiffsep_device *)pdev;
2060
0
    int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
2061
0
    int num_order = tfdev->devn_params.num_separation_order_names;
2062
0
    int num_spot = tfdev->devn_params.separations.num_separations;
2063
0
    int num_comp, comp_num, code = 0, code1 = 0;
2064
0
    cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
2065
0
    char *name = NULL;
2066
0
    int save_depth = pdev->color_info.depth;
2067
0
    int save_numcomps = pdev->color_info.num_components;
2068
0
    const char *fmt;
2069
0
    gs_parsed_file_name_t parsed;
2070
0
    int plane_count = 0;  /* quiet compiler */
2071
0
    int factor = tfdev->downscale.downscale_factor;
2072
0
    int dst_bpc = tfdev->BitsPerComponent;
2073
0
    gx_downscaler_t ds;
2074
0
    int width = gx_downscaler_scale(tfdev->width, factor);
2075
0
    int height = gx_downscaler_scale(tfdev->height, factor);
2076
2077
0
    name = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep_print_page(name)");
2078
0
    if (!name)
2079
0
        return_error(gs_error_VMerror);
2080
2081
    /*
2082
     * Since different pages may have different spot colors, if this is for a
2083
     * page after Page 1, we require that each output file is unique with a "fmt"
2084
     * (i.e. %d) as part of the filename. We create individual separation files
2085
     * for each page of the input.
2086
     * Since the TIFF lib requires seeakable files, /dev/null or nul: are
2087
     * not allowed (as they are with the psdcmyk devices).
2088
    */
2089
0
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
2090
0
                                     strlen(tfdev->fname), pdev->memory);
2091
0
    if (code < 0 || (fmt == NULL && tfdev->PageCount > 0)) {
2092
0
       emprintf(tfdev->memory,
2093
0
                "\nUse of the %%d format is required to output more than one page to tiffsep.\n"
2094
0
                "See doc/Devices.htm#TIFF for details.\n\n");
2095
0
       code = gs_note_error(gs_error_ioerror);
2096
0
       goto done;
2097
0
    }
2098
    /* Write the page directory for the CMYK equivalent file. */
2099
0
    if (!tfdev->comp_file) {
2100
0
        pdev->color_info.depth = dst_bpc*4;        /* Create directory for 32 bit cmyk */
2101
0
        if (!tfdev->UseBigTIFF && tfdev->Compression==COMPRESSION_NONE &&
2102
0
            height > ((unsigned long) 0xFFFFFFFF - (file ? gp_ftell(file) : 0))/(width*4)) { /* note width is never 0 in print_page */
2103
0
            dmprintf(pdev->memory, "CMYK composite file would be too large! Reduce resolution or enable compression.\n");
2104
0
            return_error(gs_error_rangecheck);  /* this will overflow 32 bits */
2105
0
        }
2106
2107
0
        code = gx_device_open_output_file((gx_device *)pdev, pdev->fname, true, true, &(tfdev->comp_file));
2108
0
        if (code < 0) {
2109
0
            goto done;
2110
0
        }
2111
2112
0
        tfdev->tiff_comp = tiff_from_filep(pdev, pdev->dname, tfdev->comp_file, tfdev->BigEndian, tfdev->UseBigTIFF);
2113
0
        if (!tfdev->tiff_comp) {
2114
0
            code = gs_note_error(gs_error_invalidfileaccess);
2115
0
            goto done;
2116
0
        }
2117
2118
0
    }
2119
0
    code = tiff_set_fields_for_printer(pdev, tfdev->tiff_comp, factor, 0, tfdev->write_datetime);
2120
2121
0
    if (dst_bpc == 1 || dst_bpc == 8) {
2122
0
        tiff_set_cmyk_fields(pdev, tfdev->tiff_comp, dst_bpc, tfdev->Compression, tfdev->MaxStripSize);
2123
0
    }
2124
0
    else {
2125
        /* Catch-all just for safety's sake */
2126
0
        tiff_set_cmyk_fields(pdev, tfdev->tiff_comp, dst_bpc, COMPRESSION_NONE, tfdev->MaxStripSize);
2127
0
    }
2128
2129
0
    pdev->color_info.depth = save_depth;
2130
0
    if (code < 0) {
2131
0
        goto done;
2132
0
    }
2133
2134
    /* Set up the separation output files */
2135
0
    num_comp = number_output_separations( tfdev->color_info.num_components,
2136
0
                                        num_std_colorants, num_order, num_spot);
2137
0
    tfdev->page_num_comps = num_comp;
2138
2139
0
    if (!tfdev->NoSeparationFiles && !num_order && num_comp < num_std_colorants + num_spot) {
2140
0
        dmlprintf(pdev->memory, "Warning: skipping one or more colour separations, see: Devices.htm#TIFF\n");
2141
0
    }
2142
2143
0
    if (!tfdev->NoSeparationFiles) {
2144
0
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2145
0
            int sep_num = tfdev->devn_params.separation_order_map[comp_num];
2146
2147
0
            code = create_separation_file_name(tfdev, name, gp_file_name_sizeof,
2148
0
                sep_num, true);
2149
0
            if (code < 0) {
2150
0
                goto done;
2151
0
            }
2152
2153
            /*
2154
             * Close the old separation file if we are creating individual files
2155
             * for each page.
2156
             */
2157
0
            if (tfdev->sep_file[comp_num] != NULL && fmt != NULL) {
2158
0
                code = tiffsep_close_sep_file(tfdev, name, comp_num);
2159
0
                if (code >= 0)
2160
0
                    code = gs_remove_outputfile_control_path(tfdev->memory, name);
2161
0
                if (code < 0)
2162
0
                    return code;
2163
0
            }
2164
            /* Open the separation file, if not already open */
2165
0
            if (tfdev->sep_file[comp_num] == NULL) {
2166
0
                code = gs_add_outputfile_control_path(tfdev->memory, name);
2167
0
                if (code < 0) {
2168
0
                    goto done;
2169
0
                }
2170
0
                code = gx_device_open_output_file((gx_device *)pdev, name,
2171
0
                    true, true, &(tfdev->sep_file[comp_num]));
2172
0
                if (code < 0) {
2173
0
                    goto done;
2174
0
                }
2175
0
                tfdev->tiff[comp_num] = tiff_from_filep(pdev, name,
2176
0
                    tfdev->sep_file[comp_num],
2177
0
                    tfdev->BigEndian, tfdev->UseBigTIFF);
2178
0
                if (!tfdev->tiff[comp_num]) {
2179
0
                    code = gs_note_error(gs_error_ioerror);
2180
0
                    goto done;
2181
0
                }
2182
0
            }
2183
2184
0
            pdev->color_info.depth = dst_bpc;     /* Create files for 8 bit gray */
2185
0
            pdev->color_info.num_components = 1;
2186
0
            if (!tfdev->UseBigTIFF && tfdev->Compression == COMPRESSION_NONE &&
2187
0
                height * 8 / dst_bpc > ((unsigned long)0xFFFFFFFF - (file ? gp_ftell(file) : 0)) / width) /* note width is never 0 in print_page */
2188
0
            {
2189
0
                code = gs_note_error(gs_error_rangecheck);  /* this will overflow 32 bits */
2190
0
                goto done;
2191
0
            }
2192
2193
2194
0
            code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num], factor, 0, tfdev->write_datetime);
2195
0
            tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], dst_bpc, tfdev->Compression, tfdev->MaxStripSize);
2196
0
            pdev->color_info.depth = save_depth;
2197
0
            pdev->color_info.num_components = save_numcomps;
2198
0
            if (code < 0) {
2199
0
                goto done;
2200
0
            }
2201
0
        }
2202
0
    }
2203
2204
0
    build_cmyk_map((gx_device *)tfdev, num_comp, &tfdev->equiv_cmyk_colors, cmyk_map);
2205
0
    if (tfdev->PrintSpotCMYK) {
2206
0
        code = print_cmyk_equivalent_colors(tfdev, num_comp, cmyk_map);
2207
0
        if (code < 0) {
2208
0
            goto done;
2209
0
        }
2210
0
    }
2211
2212
0
    {
2213
0
        int raster_plane = bitmap_raster(width * 8);
2214
0
        byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS] = { 0 };
2215
0
        int cmyk_raster = width * NUM_CMYK_COMPONENTS;
2216
0
        int pixel, y;
2217
0
        byte * sep_line;
2218
0
        int plane_index;
2219
0
        int offset_plane = 0;
2220
2221
0
        sep_line =
2222
0
            gs_alloc_bytes(pdev->memory, cmyk_raster, "tiffsep_print_page");
2223
0
        if (!sep_line) {
2224
0
            code = gs_note_error(gs_error_VMerror);
2225
0
            goto done;
2226
0
        }
2227
2228
0
        if (!tfdev->NoSeparationFiles)
2229
0
            for (comp_num = 0; comp_num < num_comp; comp_num++ )
2230
0
                TIFFCheckpointDirectory(tfdev->tiff[comp_num]);
2231
0
        TIFFCheckpointDirectory(tfdev->tiff_comp);
2232
2233
        /* Write the page data. */
2234
0
        {
2235
0
            gs_get_bits_params_t params;
2236
0
            int byte_width;
2237
2238
            /* Return planar data */
2239
0
            params.options = (GB_RETURN_POINTER | GB_RETURN_COPY |
2240
0
                 GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
2241
0
                 GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE);
2242
0
            params.x_offset = 0;
2243
0
            params.raster = bitmap_raster(width * pdev->color_info.depth);
2244
2245
0
            if (num_order > 0) {
2246
                /* In this case, there was a specification for a separation
2247
                   color order, which indicates what colorants we will
2248
                   actually creat individual separation files for.  We need
2249
                   to allocate for the standard colorants.  This is due to the
2250
                   fact that even when we specify a single spot colorant, we
2251
                   still create the composite CMYK output file. */
2252
0
                for (comp_num = 0; comp_num < num_std_colorants; comp_num++) {
2253
0
                    planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane,
2254
0
                                                      "tiffsep_print_page");
2255
0
                    params.data[comp_num] = planes[comp_num];
2256
0
                    if (params.data[comp_num] == NULL) {
2257
0
                        code = gs_note_error(gs_error_VMerror);
2258
0
                        goto cleanup;
2259
0
                    }
2260
0
                }
2261
0
                offset_plane = num_std_colorants;
2262
                /* Now we need to make sure that we do not allocate extra
2263
                   planes if any of the colorants in the order list are
2264
                   one of the standard colorant names */
2265
0
                plane_index = plane_count = num_std_colorants;
2266
0
                for (comp_num = 0; comp_num < num_comp; comp_num++) {
2267
0
                    int temp_pos;
2268
2269
0
                    temp_pos = tfdev->devn_params.separation_order_map[comp_num];
2270
0
                    if (temp_pos >= num_std_colorants) {
2271
                        /* We have one that is not a standard colorant name
2272
                           so allocate a new plane */
2273
0
                        planes[plane_count] = gs_alloc_bytes(pdev->memory, raster_plane,
2274
0
                                                        "tiffsep_print_page");
2275
                        /* Assign the new plane to the appropriate position */
2276
0
                        params.data[plane_index] = planes[plane_count];
2277
0
                        if (params.data[plane_index] == NULL) {
2278
0
                            code = gs_note_error(gs_error_VMerror);
2279
0
                            goto cleanup;
2280
0
                        }
2281
0
                        plane_count += 1;
2282
0
                    } else {
2283
                        /* Assign params.data with the appropriate std.
2284
                           colorant plane position */
2285
0
                        params.data[plane_index] = planes[temp_pos];
2286
0
                    }
2287
0
                    plane_index += 1;
2288
0
                }
2289
0
            } else {
2290
                /* Sep color order number was not specified so just render all
2291
                   the  planes that we can */
2292
0
                for (comp_num = 0; comp_num < num_comp; comp_num++) {
2293
0
                    planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane,
2294
0
                                                    "tiffsep_print_page");
2295
0
                    params.data[comp_num] = planes[comp_num];
2296
0
                    if (params.data[comp_num] == NULL) {
2297
0
                        code = gs_note_error(gs_error_VMerror);
2298
0
                        goto cleanup;
2299
0
                    }
2300
0
                }
2301
0
            }
2302
0
            code = gx_downscaler_init_planar(&ds, (gx_device *)pdev,
2303
0
                                             8, dst_bpc, num_comp,
2304
0
                                             &tfdev->downscale,
2305
0
                                             &params);
2306
0
            if (code < 0)
2307
0
                goto cleanup;
2308
0
            byte_width = (width * dst_bpc + 7)>>3;
2309
0
            for (y = 0; y < height; ++y) {
2310
0
                code = gx_downscaler_get_bits_rectangle(&ds, &params, y);
2311
0
                if (code < 0)
2312
0
                    goto cleanup;
2313
                /* Write separation data (tiffgray format) */
2314
0
                if (!tfdev->NoSeparationFiles) {
2315
0
                    for (comp_num = 0; comp_num < num_comp; comp_num++) {
2316
0
                        byte *src;
2317
0
                        byte *dest = sep_line;
2318
2319
0
                        if (num_order > 0) {
2320
0
                            src = params.data[tfdev->devn_params.separation_order_map[comp_num]];
2321
0
                        }
2322
0
                        else
2323
0
                            src = params.data[comp_num];
2324
0
                        for (pixel = 0; pixel < byte_width; pixel++, dest++, src++)
2325
0
                            *dest = MAX_COLOR_VALUE - *src;    /* Gray is additive */
2326
0
                        TIFFWriteScanline(tfdev->tiff[comp_num], (tdata_t)sep_line, y, 0);
2327
0
                    }
2328
0
                }
2329
                /* Write CMYK equivalent data */
2330
0
                switch(dst_bpc)
2331
0
                {
2332
0
                default:
2333
0
                case 8:
2334
0
                    build_cmyk_raster_line_fromplanar(&params, sep_line, width,
2335
0
                                                      num_comp, cmyk_map, num_order,
2336
0
                                                      tfdev);
2337
0
                    break;
2338
0
                case 4:
2339
0
                    build_cmyk_raster_line_fromplanar_4bpc(&params, sep_line, width,
2340
0
                                                           num_comp, cmyk_map, num_order,
2341
0
                                                           tfdev);
2342
0
                    break;
2343
0
                case 2:
2344
0
                    build_cmyk_raster_line_fromplanar_2bpc(&params, sep_line, width,
2345
0
                                                           num_comp, cmyk_map, num_order,
2346
0
                                                           tfdev);
2347
0
                    break;
2348
0
                case 1:
2349
0
                    build_cmyk_raster_line_fromplanar_1bpc(&params, sep_line, width,
2350
0
                                                           num_comp, cmyk_map, num_order,
2351
0
                                                           tfdev);
2352
0
                    break;
2353
0
                }
2354
0
                TIFFWriteScanline(tfdev->tiff_comp, (tdata_t)sep_line, y, 0);
2355
0
            }
2356
0
cleanup:
2357
0
            if (num_order > 0) {
2358
                /* Free up the standard colorants if num_order was set.
2359
                   In this process, we need to make sure that none of them
2360
                   were the standard colorants.  plane_count should have
2361
                   the sum of the std. colorants plus any non-standard
2362
                   ones listed in separation color order */
2363
0
                for (comp_num = 0; comp_num < plane_count; comp_num++) {
2364
0
                    gs_free_object(pdev->memory, planes[comp_num],
2365
0
                                                    "tiffsep_print_page");
2366
0
                }
2367
0
            } else {
2368
0
                for (comp_num = 0; comp_num < num_comp; comp_num++) {
2369
0
                    gs_free_object(pdev->memory, planes[comp_num + offset_plane],
2370
0
                                                    "tiffsep_print_page");
2371
0
                }
2372
0
            }
2373
0
            gx_downscaler_fin(&ds);
2374
0
            gs_free_object(pdev->memory, sep_line, "tiffsep_print_page");
2375
0
        }
2376
0
        code1 = code;
2377
0
        if (!tfdev->NoSeparationFiles) {
2378
0
            for (comp_num = 0; comp_num < num_comp; comp_num++) {
2379
0
                TIFFWriteDirectory(tfdev->tiff[comp_num]);
2380
0
                if (fmt) {
2381
0
                    int sep_num = tfdev->devn_params.separation_order_map[comp_num];
2382
2383
0
                    code = create_separation_file_name(tfdev, name, gp_file_name_sizeof, sep_num, false);
2384
0
                    if (code < 0) {
2385
0
                        code1 = code;
2386
0
                        continue;
2387
0
                    }
2388
0
                    code = tiffsep_close_sep_file(tfdev, name, comp_num);
2389
0
                    if (code >= 0)
2390
0
                        code = gs_remove_outputfile_control_path(tfdev->memory, name);
2391
0
                    if (code < 0) {
2392
0
                        code1 = code;
2393
0
                    }
2394
0
                }
2395
0
            }
2396
0
        }
2397
0
        TIFFWriteDirectory(tfdev->tiff_comp);
2398
0
        code = tiffsep_close_comp_file(tfdev, pdev->fname);
2399
0
        if (code1 < 0) {
2400
0
            code = code1;
2401
0
        }
2402
0
    }
2403
2404
0
done:
2405
0
    if (name)
2406
0
        gs_free_object(pdev->memory, name, "tiffsep_print_page(name)");
2407
0
    return code;
2408
0
}
2409
2410
/*
2411
 * Output the image data for the tiff separation (tiffsep1) device.  The data
2412
 * for the tiffsep1 device is written in separate planes to separate files.
2413
 *
2414
 * The DeviceN parameters (SeparationOrder, SeparationColorNames, and
2415
 * MaxSeparations) are applied to the tiffsep device.
2416
 */
2417
static int
2418
tiffsep1_print_page(gx_device_printer * pdev, gp_file * file)
2419
597
{
2420
597
    tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
2421
597
    int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
2422
597
    int num_order = tfdev->devn_params.num_separation_order_names;
2423
597
    int num_spot = tfdev->devn_params.separations.num_separations;
2424
597
    int num_comp, comp_num, code = 0, code1 = 0;
2425
597
    bool double_f = false;
2426
597
    int base_filename_length = length_base_file_name((tiffsep_device *)tfdev, &double_f);
2427
597
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
2428
597
    char *name = NULL;
2429
597
    int save_depth = pdev->color_info.depth;
2430
597
    int save_numcomps = pdev->color_info.num_components;
2431
597
    const char *fmt;
2432
597
    gs_parsed_file_name_t parsed;
2433
597
    int non_encodable_count = 0;
2434
597
    cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
2435
2436
597
    name = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_print_page(name)");
2437
597
    if (!name)
2438
0
        return_error(gs_error_VMerror);
2439
2440
597
    build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
2441
2442
    /* Print the names of the spot colors */
2443
597
    if (num_order == 0) {
2444
610
        for (comp_num = 0; comp_num < num_spot; comp_num++) {
2445
13
            copy_separation_name((tiffsep_device *)tfdev, name,
2446
13
                gp_file_name_sizeof - base_filename_length - SUFFIX_SIZE, comp_num, 0);
2447
13
            dmlprintf1(pdev->memory, "%%%%SeparationName: %s", name);
2448
13
            dmlprintf4(pdev->memory, " CMYK = [ %d %d %d %d ]\n",
2449
13
                tfdev->equiv_cmyk_colors.color[comp_num].c,
2450
13
                tfdev->equiv_cmyk_colors.color[comp_num].m,
2451
13
                tfdev->equiv_cmyk_colors.color[comp_num].y,
2452
13
                tfdev->equiv_cmyk_colors.color[comp_num].k
2453
13
            );
2454
13
        }
2455
597
    }
2456
    /*
2457
     * Since different pages may have different spot colors, if this is for a
2458
     * page after Page 1, we require that each output file is unique with a "fmt"
2459
     * (i.e. %d) as part of the filename. We create individual separation files
2460
     * for each page of the input.
2461
     * Since the TIFF lib requires seeakable files, /dev/null or nul: are
2462
     * not allowed (as they are with the psdcmyk devices).
2463
    */
2464
597
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
2465
597
                                     strlen(tfdev->fname), pdev->memory);
2466
597
    if (code < 0 || (fmt == NULL && tfdev->PageCount > 0)) {
2467
370
       emprintf(tfdev->memory,
2468
370
                "\nUse of the %%d format is required to output more than one page to tiffsep1.\n"
2469
370
                "See doc/Devices.htm#TIFF for details.\n\n");
2470
370
       code = gs_note_error(gs_error_ioerror);
2471
370
       goto done;
2472
370
    }
2473
    /* If the output file is on disk and the name contains a page #, */
2474
    /* then delete the previous file. */
2475
227
    if (pdev->file != NULL && parsed.iodev == iodev_default(pdev->memory) && fmt) {
2476
0
        char *compname = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_print_page(compname)");
2477
0
        if (!compname) {
2478
0
            code = gs_note_error(gs_error_VMerror);
2479
0
            goto done;
2480
0
        }
2481
0
#ifndef PPM_COMBINED_OUTPUT
2482
0
        {
2483
0
            long count1 = pdev->PageCount;
2484
2485
0
            gx_device_close_output_file((gx_device *)pdev, pdev->fname, pdev->file);
2486
0
            pdev->file = NULL;
2487
0
            while (*fmt != 'l' && *fmt != '%')
2488
0
                --fmt;
2489
0
            if (*fmt == 'l')
2490
0
                gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, count1);
2491
0
            else
2492
0
                gs_snprintf(compname, gp_file_name_sizeof, parsed.fname, (int)count1);
2493
0
            parsed.iodev->procs.delete_file(parsed.iodev, compname);
2494
0
        }
2495
0
#endif  /* PPM_COMBINED_OUTPUT */
2496
2497
        /* we always need an open printer (it will get deleted in tiffsep1_prn_close */
2498
0
        code = gdev_prn_open_printer((gx_device *)pdev, 1);
2499
2500
0
        gs_free_object(pdev->memory, compname, "tiffsep_print_page(compname)");
2501
0
        if (code < 0) {
2502
0
            goto done;
2503
0
        }
2504
0
    }
2505
    /* Set up the separation output files */
2506
227
    num_comp = number_output_separations(tfdev->color_info.num_components,
2507
227
                                         num_std_colorants, num_order, num_spot);
2508
227
    tfdev->page_num_comps = num_comp;
2509
2510
227
    build_cmyk_map((gx_device *)tfdev, num_comp, &tfdev->equiv_cmyk_colors, cmyk_map);
2511
227
    if (tfdev->PrintSpotCMYK) {
2512
0
        code = print_cmyk_equivalent_colors((tiffsep_device *)tfdev, num_comp, cmyk_map);
2513
0
        if (code < 0) {
2514
0
            goto done;
2515
0
        }
2516
0
    }
2517
1.14k
    for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2518
914
        int sep_num = map_comp_to_sep[comp_num];
2519
2520
914
        code = create_separation_file_name((tiffsep_device *)tfdev, name,
2521
914
                                        gp_file_name_sizeof, sep_num, true);
2522
914
        if (code < 0) {
2523
0
            goto done;
2524
0
        }
2525
2526
        /* Open the separation file, if not already open */
2527
914
        if (tfdev->sep_file[comp_num] == NULL) {
2528
914
            code = gs_add_outputfile_control_path(tfdev->memory, name);
2529
914
            if (code < 0) {
2530
0
                goto done;
2531
0
            }
2532
914
            code = gx_device_open_output_file((gx_device *)pdev, name,
2533
914
                    true, true, &(tfdev->sep_file[comp_num]));
2534
914
            if (code < 0) {
2535
0
                goto done;
2536
0
            }
2537
914
            tfdev->tiff[comp_num] = tiff_from_filep(pdev, name,
2538
914
                                                    tfdev->sep_file[comp_num],
2539
914
                                                    tfdev->BigEndian, tfdev->UseBigTIFF);
2540
914
            if (!tfdev->tiff[comp_num]) {
2541
0
                code = gs_note_error(gs_error_ioerror);
2542
0
                goto done;
2543
0
            }
2544
914
        }
2545
2546
914
        pdev->color_info.depth = 1;
2547
914
        pdev->color_info.num_components = 1;
2548
914
        code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num], 1, 0, tfdev->write_datetime);
2549
914
        tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], 1, tfdev->Compression, tfdev->MaxStripSize);
2550
914
        pdev->color_info.depth = save_depth;
2551
914
        pdev->color_info.num_components = save_numcomps;
2552
914
        if (code < 0) {
2553
0
            goto done;
2554
0
        }
2555
2556
914
    }   /* end initialization of separation files */
2557
2558
2559
227
    {   /* Get the halftoned line and write out the separations */
2560
227
        byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS];
2561
227
        int width = tfdev->width;
2562
227
        int raster_plane = bitmap_raster(width);
2563
227
        int y;
2564
227
        gs_get_bits_params_t params;
2565
227
        gs_int_rect rect;
2566
2567
        /* the line is assumed to be 32-bit aligned by the alloc */
2568
227
        memset(planes, 0, sizeof(*planes) * GS_CLIENT_COLOR_MAX_COMPONENTS);
2569
2570
        /* Return planar data */
2571
227
        params.options = (GB_RETURN_POINTER | GB_RETURN_COPY |
2572
227
             GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
2573
227
             GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE);
2574
227
        params.x_offset = 0;
2575
227
        params.raster = bitmap_raster(width * pdev->color_info.depth);
2576
2577
227
        code = 0;
2578
1.14k
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2579
914
            planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane,
2580
914
                                            "tiffsep1_print_page");
2581
914
            if (planes[comp_num] == NULL) {
2582
0
                code = gs_error_VMerror;
2583
0
                break;
2584
0
            }
2585
914
        }
2586
2587
1.14k
        for (comp_num = 0; comp_num < num_comp; comp_num++ )
2588
914
            TIFFCheckpointDirectory(tfdev->tiff[comp_num]);
2589
2590
227
        rect.p.x = 0;
2591
227
        rect.q.x = pdev->width;
2592
        /* Loop for the lines */
2593
442k
        for (y = 0; y < pdev->height; ++y) {
2594
442k
            rect.p.y = y;
2595
442k
            rect.q.y = y + 1;
2596
            /* We have to reset the pointers since get_bits_rect will have moved them */
2597
2.22M
            for (comp_num = 0; comp_num < num_comp; comp_num++)
2598
1.78M
                params.data[comp_num] = planes[comp_num];
2599
442k
            code = (*dev_proc(pdev, get_bits_rectangle))((gx_device *)pdev, &rect, &params);
2600
442k
            if (code < 0)
2601
0
                break;
2602
2603
            /* write it out */
2604
2.22M
            for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2605
1.78M
                int i;
2606
1.78M
                byte *src = params.data[comp_num];
2607
2608
                /* TIFF 1-bit is additive, invert the data */
2609
404M
                for (i=0; i<raster_plane; i++)
2610
402M
                    *src++ ^= 0xff;   /* invert the data */
2611
1.78M
                src = params.data[comp_num];
2612
1.78M
                TIFFWriteScanline(tfdev->tiff[comp_num], src, y, 0);
2613
1.78M
            } /* end component loop */
2614
#ifdef PPM_COMBINED_OUTPUT
2615
            {
2616
                int i;
2617
2618
                if (y == 0) {
2619
                    gp_fprintf(pdev->file, "P6\n");
2620
                    gp_fprintf(pdev->file, "# Image generated by %s (device=pkmraw)\n", gs_product);
2621
                    gp_fprintf(pdev->file, "%d %d\n255\n", pdev->width, pdev->height);
2622
                }
2623
                for (i=0; i<pdev->width; i += 8) {
2624
                    int b, ib = i>>3;
2625
                    byte C = *((byte *)(params.data[0]) + ib);
2626
                    byte M = *((byte *)(params.data[1]) + ib);
2627
                    byte Y = *((byte *)(params.data[2]) + ib);
2628
                    byte K = *((byte *)(params.data[3]) + ib);
2629
                    byte mask = 128;
2630
2631
                    for (b=7; b >= 0; b--) {
2632
                        byte RGB[3];
2633
2634
                        if (i + (8-b) > pdev->width)
2635
                            break;
2636
                        if ((K & mask) != 0) {
2637
                            RGB[0] = (C & mask) == 0 ? 0 : 255;
2638
                            RGB[1] = (M & mask) == 0 ? 0 : 255;
2639
                            RGB[2] = (Y & mask) == 0 ? 0 : 255;
2640
                        } else {
2641
                            RGB[0] = RGB[1] = RGB[2] = 0;
2642
                        }
2643
                        /* If there are any spot colors, add them in proportionally to this dot */
2644
                        if (num_comp > 4) {
2645
                            uint64_t SPOT[4] = { 0, 0, 0, 0 };  /* accumulate frac colorants */
2646
                            int s;
2647
                            uint64_t denom_scale = frac_1 * (num_comp - 3) / 255;
2648
2649
                            for (s=4; s<num_comp; s++) {
2650
                                if ((*((byte *)(params.data[s]) + ib) & mask) == 0) {
2651
                                    SPOT[0] += cmyk_map[s].c;
2652
                                    SPOT[1] += cmyk_map[s].m;
2653
                                    SPOT[2] += cmyk_map[s].y;
2654
                                    SPOT[3] += cmyk_map[s].k;
2655
                                }
2656
                            }
2657
                            for (s=0; s<4; s++)
2658
                                SPOT[s] /= denom_scale;         /* map to 0..255 range */
2659
                            RGB[0] = RGB[0] > SPOT[0] + SPOT[3] ? RGB[0] -= SPOT[0] + SPOT[3] : 0;
2660
                            RGB[1] = RGB[1] > SPOT[1] + SPOT[3] ? RGB[1] -= SPOT[1] + SPOT[3] : 0;
2661
                            RGB[2] = RGB[2] > SPOT[2] + SPOT[3] ? RGB[2] -= SPOT[2] + SPOT[3] : 0;
2662
                        }
2663
                        gp_fwrite(RGB, 3, 1, pdev->file);
2664
                        mask >>= 1;
2665
                    }
2666
                }
2667
                gp_fflush(pdev->file);
2668
            }
2669
#endif  /* PPM_COMBINED_OUTPUT */
2670
442k
        }
2671
        /* Update the strip data */
2672
1.14k
        for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2673
914
            TIFFWriteDirectory(tfdev->tiff[comp_num]);
2674
914
            if (fmt) {
2675
0
                int sep_num = map_comp_to_sep[comp_num];
2676
2677
0
                code = create_separation_file_name((tiffsep_device *)tfdev, name, gp_file_name_sizeof, sep_num, false);
2678
0
                if (code < 0) {
2679
0
                    code1 = code;
2680
0
                    continue;
2681
0
                }
2682
0
                code = tiffsep_close_sep_file((tiffsep_device *)tfdev, name, comp_num);
2683
0
                if (code >= 0)
2684
0
                    code = gs_remove_outputfile_control_path(tfdev->memory, name);
2685
0
                if (code < 0) {
2686
0
                    code1 = code;
2687
0
                }
2688
0
            }
2689
914
        }
2690
227
        code = code1;
2691
2692
        /* free any allocations and exit with code */
2693
1.14k
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2694
914
            gs_free_object(pdev->memory, planes[comp_num], "tiffsep1_print_page");
2695
914
        }
2696
227
    }
2697
    /*
2698
     * If we have any non encodable pixels then signal an error.
2699
     */
2700
227
    if (non_encodable_count) {
2701
0
        dmlprintf1(pdev->memory, "WARNING:  Non encodable pixels = %d\n", non_encodable_count);
2702
0
        code = gs_note_error(gs_error_rangecheck);
2703
0
    }
2704
2705
597
done:
2706
597
    if (name)
2707
597
        gs_free_object(pdev->memory, name, "tiffsep1_print_page(name)");
2708
597
    return code;
2709
227
}
2710
2711
/*
2712
 * Encode a list of colorant values into a gx_color_index_value.
2713
 */
2714
static gx_color_index
2715
tiffsep1_encode_color(gx_device *dev, const gx_color_value colors[])
2716
7.64M
{
2717
7.64M
    gx_color_index color = 0;
2718
7.64M
    int i = 0;
2719
7.64M
    int ncomp = dev->color_info.num_components;
2720
2721
38.2M
    for (; i < ncomp; i++) {
2722
30.6M
        color <<= 1;
2723
30.6M
        color |= colors[i] == gx_max_color_value;
2724
30.6M
    }
2725
7.64M
    return (color == gx_no_color_index ? color ^ 1 : color);
2726
7.64M
}
2727
2728
/*
2729
 * Decode a gx_color_index value back to a list of colorant values.
2730
 */
2731
static int
2732
tiffsep1_decode_color(gx_device * dev, gx_color_index color, gx_color_value * out)
2733
0
{
2734
0
    int i = 0;
2735
0
    int ncomp = dev->color_info.num_components;
2736
2737
0
    for (; i < ncomp; i++) {
2738
0
        out[ncomp - i - 1] = (color & 1) ? gx_max_color_value : 0;
2739
0
        color >>= 1;
2740
0
    }
2741
0
    return 0;
2742
0
}
2743
2744
/* The tiffscaled contone devices have to be able to change their color model
2745
to allow a more flexible use of the post render ICC profile with the output
2746
intent. For example, if we are wanting to render to a CMYK intermediate
2747
output intent but we want the output to be in sRGB then we need to use
2748
-sDEVICE=tiffscaled24 -dUsePDFX3Profile -sOutputICCProfile=default_cmyk.icc
2749
-sPostRenderProfile=srgb.icc .  This should then render to a temporary
2750
buffer the is in the OutputIntent color space and then be converted to
2751
sRGB.  This should look like the result we get when we go out to the
2752
tiffscaled32 device. This is in contrast to the command line
2753
sDEVICE=tiffscaled24 -dUsePDFX3Profile -sPostRenderProfile=srgb.icc which would
2754
end up using the output intent as a proofing profile.  The results may be similar
2755
but not exact as overprint and spot colors would not appear correctly due to the
2756
additive color model during rendering. */
2757
int
2758
tiff_open_s(gx_device *pdev)
2759
0
{
2760
0
    int code;
2761
2762
    /* Take care of any color model changes now */
2763
0
    if (pdev->icc_struct->postren_profile != NULL &&
2764
0
        pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps != pdev->color_info.num_components &&
2765
0
        pdev->color_info.depth == 8 * pdev->color_info.num_components) {
2766
2767
0
        code = gx_change_color_model((gx_device*)pdev,
2768
0
            pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps, 8);
2769
0
        if (code < 0)
2770
0
            return code;
2771
2772
        /* Reset the device procs */
2773
0
        memset(&(pdev->procs), 0, sizeof(pdev->procs));
2774
0
        switch (pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps) {
2775
0
        case 1:
2776
0
            pdev->initialize_device_procs = tiffscaled8_initialize_device_procs;
2777
0
            pdev->color_info.dither_colors = 0;
2778
0
            pdev->color_info.max_color = 0;
2779
0
            break;
2780
0
        case 3:
2781
0
            pdev->initialize_device_procs = tiffscaled24_initialize_device_procs;
2782
0
            pdev->color_info.dither_colors = 0;
2783
0
            pdev->color_info.max_color = 0;
2784
0
            break;
2785
0
        case 4:
2786
0
            pdev->initialize_device_procs = tiffscaled32_initialize_device_procs;
2787
0
            pdev->color_info.dither_colors = 256;
2788
0
            pdev->color_info.max_color = 255;
2789
0
            break;
2790
0
        }
2791
0
        pdev->initialize_device_procs(pdev);
2792
        /* We know pdev->procs.initialize_device is NULL */
2793
0
        check_device_separable(pdev);
2794
0
        gx_device_fill_in_procs(pdev);
2795
0
    }
2796
0
    return tiff_open(pdev);
2797
0
}