Coverage Report

Created: 2026-07-24 07:44

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