Coverage Report

Created: 2026-02-14 07:09

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
19.9k
{
325
19.9k
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
326
19.9k
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
327
19.9k
    TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
328
19.9k
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
329
330
19.9k
    tiff_set_compression(pdev, tif, compression, max_strip_size);
331
19.9k
}
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
12.3M
{
544
12.3M
    if (op == gxdso_supports_iccpostrender || op == gxdso_supports_devn
545
12.3M
     || op == gxdso_skip_icc_component_validation) {
546
20.2k
        return true;
547
20.2k
    }
548
12.3M
    return gdev_prn_dev_spec_op(dev_, op, data, datasize);
549
12.3M
}
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
1.08M
ENUM_PTRS_WITH(tiffsep_device_enum_ptrs, tiffsep_device *pdev)
706
1.08M
{
707
1.08M
    if (index < pdev->devn_params.separations.num_separations)
708
65
        ENUM_RETURN(pdev->devn_params.separations.names[index].data);
709
1.08M
    ENUM_PREFIX(st_device_printer,
710
0
                    pdev->devn_params.separations.num_separations);
711
0
    return 0;
712
1.08M
}
713
1.08M
ENUM_PTRS_END
714
715
21.2k
static RELOC_PTRS_WITH(tiffsep_device_reloc_ptrs, tiffsep_device *pdev)
716
21.2k
{
717
21.2k
    RELOC_PREFIX(st_device_printer);
718
21.2k
    {
719
21.2k
        int i;
720
721
21.2k
        for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
722
65
            RELOC_PTR(tiffsep_device, devn_params.separations.names[i].data);
723
65
        }
724
21.2k
    }
725
21.2k
}
726
21.2k
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
10.1k
{
734
    /* We need to deallocate the names. */
735
10.1k
    devn_free_params((gx_device*) vpdev);
736
10.1k
    gx_device_finalize(cmem, vpdev);
737
10.1k
}
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
10.1k
{
746
10.1k
    gdev_prn_initialize_device_procs(dev);
747
748
10.1k
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
749
10.1k
    set_dev_proc(dev, open_device, tiffsep_prn_open);
750
10.1k
    set_dev_proc(dev, close_device, tiffsep_prn_close);
751
10.1k
    set_dev_proc(dev, map_color_rgb, tiffsep_decode_color);
752
10.1k
    set_dev_proc(dev, get_params, tiffsep_get_params);
753
10.1k
    set_dev_proc(dev, put_params, tiffsep_put_params);
754
10.1k
    set_dev_proc(dev, get_color_mapping_procs, tiffsep_get_color_mapping_procs);
755
10.1k
    set_dev_proc(dev, get_color_comp_index, tiffsep_get_color_comp_index);
756
10.1k
    set_dev_proc(dev, encode_color, tiffsep_encode_color);
757
10.1k
    set_dev_proc(dev, decode_color, tiffsep_decode_color);
758
10.1k
    set_dev_proc(dev, update_spot_equivalent_colors, tiffsep_update_spot_equivalent_colors);
759
10.1k
    set_dev_proc(dev, ret_devn_params, tiffsep_ret_devn_params);
760
10.1k
    set_dev_proc(dev, dev_spec_op, tiffsep_spec_op);
761
10.1k
}
762
763
static void
764
tiffsep1_initialize_device_procs(gx_device *dev)
765
10.1k
{
766
10.1k
    tiffsep_initialize_device_procs(dev);
767
10.1k
    set_dev_proc(dev, open_device, tiffsep1_prn_open);
768
10.1k
    set_dev_proc(dev, close_device, tiffsep1_prn_close);
769
10.1k
    set_dev_proc(dev, encode_color, tiffsep1_encode_color);
770
10.1k
    set_dev_proc(dev, decode_color, tiffsep1_decode_color);
771
10.1k
    set_dev_proc(dev, map_color_rgb, cmyk_1bit_map_color_rgb);
772
10.1k
}
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
8.32k
{
854
8.32k
    int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
855
856
8.32k
    gray_cs_to_devn_cm(dev, map, gray, out);
857
8.32k
}
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
20.7M
{
872
20.7M
    const gs_devn_params *devn = tiffsep_ret_devn_params_const(dev);
873
20.7M
    const int *map = devn->separation_order_map;
874
20.7M
    int j;
875
876
20.7M
    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
20.7M
    } else {
901
20.7M
        cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
902
20.7M
    }
903
20.7M
}
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
20.7M
{
918
20.7M
    *tdev = dev;
919
20.7M
    return &tiffsep_cm_procs;
920
20.7M
}
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.60k
{
969
1.60k
    tiffsep_device * pdev = (tiffsep_device *)dev;
970
971
1.60k
    update_spot_equivalent_cmyk_colors(dev, pgs, pcs,
972
1.60k
                    &pdev->devn_params, &pdev->equiv_cmyk_colors);
973
1.60k
    return 0;
974
1.60k
}
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
9.23M
{
982
9.23M
    tiffsep_device * pdev = (tiffsep_device *)dev;
983
984
9.23M
    return &pdev->devn_params;
985
9.23M
}
986
987
static const gs_devn_params *
988
tiffsep_ret_devn_params_const (const gx_device * dev)
989
20.7M
{
990
20.7M
    const tiffsep_device * pdev = (const tiffsep_device *)dev;
991
992
20.7M
    return &pdev->devn_params;
993
20.7M
}
994
995
/* Get parameters.  We provide a default CRD. */
996
static int
997
tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
998
190k
{
999
190k
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1000
190k
    int code = gdev_prn_get_params(pdev, plist);
1001
190k
    int ecode = code;
1002
190k
    gs_param_string comprstr;
1003
1004
190k
    if (code < 0)
1005
0
        return code;
1006
1007
190k
    code = devn_get_params(pdev, plist,
1008
190k
                &(((tiffsep_device *)pdev)->devn_params),
1009
190k
                &(((tiffsep_device *)pdev)->equiv_cmyk_colors));
1010
190k
    if (code < 0)
1011
0
        return code;
1012
1013
190k
    if ((code = param_write_bool(plist, "NoSeparationFiles", &pdevn->NoSeparationFiles)) < 0)
1014
0
        ecode = code;
1015
190k
    if ((code = param_write_bool(plist, "BigEndian", &pdevn->BigEndian)) < 0)
1016
0
        ecode = code;
1017
190k
    if ((code = param_write_bool(plist, "TIFFDateTime", &pdevn->write_datetime)) < 0)
1018
0
        ecode = code;
1019
190k
    if ((code = tiff_compression_param_string(&comprstr, pdevn->Compression)) < 0 ||
1020
190k
        (code = param_write_string(plist, "Compression", &comprstr)) < 0)
1021
0
        ecode = code;
1022
190k
    if ((code = param_write_long(plist, "MaxStripSize", &pdevn->MaxStripSize)) < 0)
1023
0
        ecode = code;
1024
190k
    if ((code = param_write_long(plist, "BitsPerComponent", &pdevn->BitsPerComponent)) < 0)
1025
0
        ecode = code;
1026
190k
    if ((code = param_write_int(plist, "MaxSpots", &pdevn->max_spots)) < 0)
1027
0
        ecode = code;
1028
190k
    if ((code = param_write_bool(plist, "LockColorants", &pdevn->lock_colorants)) < 0)
1029
0
        ecode = code;
1030
190k
    if ((code = param_write_bool(plist, "PrintSpotCMYK", &pdevn->PrintSpotCMYK)) < 0)
1031
0
        ecode = code;
1032
190k
    if ((code = gx_downscaler_write_params(plist, &pdevn->downscale,
1033
190k
                                           GX_DOWNSCALER_PARAMS_MFS |
1034
190k
                                           GX_DOWNSCALER_PARAMS_TRAP)) < 0)
1035
0
        ecode = code;
1036
1037
190k
    return ecode;
1038
190k
}
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
59.7k
{
1044
59.7k
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1045
59.7k
    int code;
1046
59.7k
    const char *param_name;
1047
59.7k
    gs_param_string comprstr;
1048
59.7k
    long bpc = pdevn->BitsPerComponent;
1049
59.7k
    int max_spots = pdevn->max_spots;
1050
1051
59.7k
    switch (code = param_read_bool(plist, (param_name = "NoSeparationFiles"),
1052
59.7k
        &pdevn->NoSeparationFiles)) {
1053
0
    default:
1054
0
        param_signal_error(plist, param_name, code);
1055
0
        return code;
1056
5.44k
    case 0:
1057
59.7k
    case 1:
1058
59.7k
        break;
1059
59.7k
    }
1060
    /* Read BigEndian option as bool */
1061
59.7k
    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
5.44k
        case 0:
1066
59.7k
        case 1:
1067
59.7k
            break;
1068
59.7k
    }
1069
59.7k
    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
5.44k
        case 0:
1073
59.7k
        case 1:
1074
59.7k
            break;
1075
59.7k
    }
1076
59.7k
    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
5.44k
        case 0:
1081
59.7k
        case 1:
1082
59.7k
            break;
1083
59.7k
    }
1084
1085
59.7k
    switch (code = param_read_long(plist, (param_name = "BitsPerComponent"), &bpc)) {
1086
5.44k
        case 0:
1087
5.44k
            if ((bpc == 1) || (bpc == 8)) {
1088
5.44k
                pdevn->BitsPerComponent = bpc;
1089
5.44k
                break;
1090
5.44k
            }
1091
0
            code = gs_error_rangecheck;
1092
0
        default:
1093
0
            param_signal_error(plist, param_name, code);
1094
0
            return code;
1095
54.3k
        case 1:
1096
54.3k
            break;
1097
59.7k
    }
1098
1099
    /* Read Compression */
1100
59.7k
    switch (code = param_read_string(plist, (param_name = "Compression"), &comprstr)) {
1101
5.44k
        case 0:
1102
5.44k
            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
5.44k
            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
5.44k
            break;
1116
54.3k
        case 1:
1117
54.3k
            break;
1118
0
        default:
1119
0
            param_signal_error(plist, param_name, code);
1120
0
            return code;
1121
59.7k
    }
1122
59.7k
    switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &pdevn->MaxStripSize)) {
1123
5.44k
        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
5.44k
            if (pdevn->MaxStripSize >= 0)
1130
5.44k
                break;
1131
0
            code = gs_error_rangecheck;
1132
0
        default:
1133
0
            param_signal_error(plist, param_name, code);
1134
0
            return code;
1135
54.3k
        case 1:
1136
54.3k
            break;
1137
59.7k
    }
1138
59.7k
    switch (code = param_read_bool(plist, (param_name = "LockColorants"),
1139
59.7k
            &(pdevn->lock_colorants))) {
1140
5.44k
        case 0:
1141
5.44k
            break;
1142
54.3k
        case 1:
1143
54.3k
            break;
1144
0
        default:
1145
0
            param_signal_error(plist, param_name, code);
1146
0
            return code;
1147
59.7k
    }
1148
59.7k
    switch (code = param_read_int(plist, (param_name = "MaxSpots"), &max_spots)) {
1149
5.44k
        case 0:
1150
5.44k
            if ((max_spots >= 0) && (max_spots <= GS_CLIENT_COLOR_MAX_COMPONENTS-4)) {
1151
5.44k
                pdevn->max_spots = max_spots;
1152
5.44k
                break;
1153
5.44k
            }
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
54.3k
        case 1:
1158
54.3k
            break;
1159
0
        default:
1160
0
            param_signal_error(plist, param_name, code);
1161
0
            return code;
1162
59.7k
    }
1163
1164
59.7k
    code = gx_downscaler_read_params(plist, &pdevn->downscale,
1165
59.7k
                                     GX_DOWNSCALER_PARAMS_MFS | GX_DOWNSCALER_PARAMS_TRAP);
1166
59.7k
    if (code < 0)
1167
0
        return code;
1168
1169
59.7k
    code = devn_printer_put_params(pdev, plist,
1170
59.7k
                &(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
1171
1172
59.7k
    return(code);
1173
59.7k
}
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
19.4k
{
1184
19.4k
    gx_device_printer *ppdev = (gx_device_printer *)pdev;
1185
19.4k
    tiffsep1_device *pdev_sep = (tiffsep1_device *) pdev;
1186
19.4k
    int code, k;
1187
1188
    /* Use our own warning and error message handlers in libtiff */
1189
19.4k
    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
19.4k
    pdev_sep->warning_given = false;
1194
19.4k
    if (pdev_sep->devn_params.page_spot_colors >= 0) {
1195
4.62k
        pdev->color_info.num_components =
1196
4.62k
            (pdev_sep->devn_params.page_spot_colors
1197
4.62k
                                 + pdev_sep->devn_params.num_std_colorant_names);
1198
4.62k
        if (pdev->color_info.num_components > pdev->color_info.max_components)
1199
0
            pdev->color_info.num_components = pdev->color_info.max_components;
1200
14.7k
    } 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
14.7k
        int num_comp = pdev_sep->max_spots + 4; /* Spots + CMYK */
1207
14.7k
        if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS)
1208
0
            num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS;
1209
14.7k
        pdev->color_info.num_components = num_comp;
1210
14.7k
        pdev->color_info.max_components = num_comp;
1211
14.7k
    }
1212
    /* Push this to the max amount as a default if someone has not set it */
1213
19.4k
    if (pdev_sep->devn_params.num_separation_order_names == 0)
1214
1.26M
        for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
1215
1.24M
            pdev_sep->devn_params.separation_order_map[k] = k;
1216
1.24M
        }
1217
19.4k
    pdev->color_info.depth = bpc_to_depth(pdev->color_info.num_components,
1218
19.4k
                                          pdev_sep->devn_params.bitspercomponent);
1219
19.4k
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1220
19.4k
    code = gdev_prn_open_planar(pdev, pdev->color_info.num_components);
1221
19.4k
    while (pdev->child)
1222
0
        pdev = pdev->child;
1223
19.4k
    ppdev = (gx_device_printer *)pdev;
1224
19.4k
    pdev_sep = (tiffsep1_device *)pdev;
1225
1226
19.4k
    ppdev->file = NULL;
1227
19.4k
    pdev->icc_struct->supports_devn = true;
1228
1229
19.4k
    return code;
1230
19.4k
}
1231
1232
/* Close the tiffsep device */
1233
int
1234
tiffsep1_prn_close(gx_device * pdev)
1235
19.4k
{
1236
19.4k
    tiffsep1_device * const tfdev = (tiffsep1_device *) pdev;
1237
19.4k
    char *name= NULL;
1238
19.4k
    int code = gdev_prn_close(pdev);
1239
19.4k
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1240
19.4k
    int comp_num;
1241
19.4k
    const char *fmt;
1242
19.4k
    gs_parsed_file_name_t parsed;
1243
1244
19.4k
    if (code < 0)
1245
0
        return code;
1246
1247
19.4k
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
1248
19.4k
                                     strlen(tfdev->fname), pdev->memory);
1249
19.4k
    if (code < 0) {
1250
0
        goto done;
1251
0
    }
1252
1253
19.4k
#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
19.4k
    if (parsed.iodev == iodev_default(pdev->memory)) {          /* filename includes "%nnd" */
1256
19.4k
        char *compname = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_prn_close(compname)");
1257
19.4k
        if (!compname) {
1258
0
            code = gs_note_error(gs_error_VMerror);
1259
0
            goto done;
1260
0
        }
1261
1262
19.4k
        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
19.4k
        } else {
1273
19.4k
            parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname);
1274
19.4k
        }
1275
19.4k
        gs_free_object(pdev->memory, compname, "tiffsep1_prn_close(compname)");
1276
19.4k
    }
1277
19.4k
#endif
1278
1279
19.4k
    build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
1280
    /* Close the separation files */
1281
57.8k
    for (comp_num = 0; comp_num < tfdev->page_num_comps; comp_num++ ) {
1282
38.4k
        const char *lname_empty = "";
1283
38.4k
        char *lname = NULL;
1284
1285
38.4k
        if (tfdev->tiff[comp_num] != NULL) {
1286
19.9k
            tiff_filename_from_tiff(tfdev->tiff[comp_num], &name);
1287
19.9k
        }
1288
18.4k
        else {
1289
18.4k
            name = (char *)lname_empty;
1290
18.4k
        }
1291
1292
38.4k
        lname = (char *)gs_alloc_bytes(tfdev->memory, strlen(name) + 1, "tiffsep1_prn_close");
1293
38.4k
        if (lname == NULL) {
1294
0
            code = gs_note_error(gs_error_VMerror);
1295
0
            goto done;
1296
0
        }
1297
38.4k
        memcpy(lname, name, strlen(name) + 1);
1298
1299
38.4k
        if (tfdev->tiff[comp_num]) {
1300
19.9k
            void *t = TIFFClientdata(tfdev->tiff[comp_num]);
1301
1302
19.9k
            TIFFCleanup(tfdev->tiff[comp_num]);
1303
19.9k
            gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep1_prn_close");
1304
19.9k
            tfdev->tiff[comp_num] = NULL;
1305
19.9k
        }
1306
38.4k
        if (tfdev->sep_file[comp_num] != NULL) {
1307
19.9k
            code = gx_device_close_output_file(pdev, lname, tfdev->sep_file[comp_num]);
1308
19.9k
            if (code >= 0)
1309
19.9k
                code = gs_remove_outputfile_control_path(pdev->memory, lname);
1310
19.9k
            if (code < 0) {
1311
0
                goto done;
1312
0
            }
1313
19.9k
            tfdev->sep_file[comp_num] = NULL;
1314
19.9k
        }
1315
38.4k
        gs_free_object(tfdev->memory, lname, "tiffsep1_prn_close");
1316
38.4k
    }
1317
1318
19.4k
done:
1319
19.4k
    return code;
1320
19.4k
}
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.55M
{
1340
1.55M
    tiffsep_device * pdev = (tiffsep_device *) dev;
1341
1.55M
    int index;
1342
1343
1.55M
    if (strncmp(pname, "None", name_size) == 0) return -1;
1344
1.55M
    index = devn_get_color_comp_index(dev,
1345
1.55M
                &(pdev->devn_params), &(pdev->equiv_cmyk_colors),
1346
1.55M
                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.55M
    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.55M
    return index;
1362
1.55M
}
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
113
{
1378
113
    int sep_size = pdev->devn_params.separations.names[sep_num].size;
1379
113
    const byte *p = pdev->devn_params.separations.names[sep_num].data;
1380
113
    int r, w, use_sep_num = 0;
1381
113
    const char *stdnames[4] = {"CYAN", "MAGENTA", "YELLOW", "BLACK"};
1382
113
    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
565
    for (r=0;r<4;r++)
1393
452
    {
1394
452
        if (strlen(stdnames[r]) == pdev->devn_params.separations.names[sep_num].size) {
1395
27
            use_sep_num = 1;
1396
27
            for (w=0;w<strlen(stdnames[r]);w++) {
1397
27
                if (toupper(pdev->devn_params.separations.names[sep_num].data[w]) != stdnames[r][w]) {
1398
27
                    use_sep_num = 0;
1399
27
                    break;
1400
27
                }
1401
27
            }
1402
27
        }
1403
452
    }
1404
113
    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
113
    r = 0;
1412
113
    w = 0;
1413
879
    while (r < sep_size && w < max_size-1 - strlen(sep_num_str))
1414
766
    {
1415
766
        int c = p[r++];
1416
766
        if (c >= 127 ||
1417
526
            !gp_file_name_good_char(c) ||
1418
526
            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
526
        else
1431
526
        {
1432
526
            buffer[w++] = c;
1433
526
        }
1434
766
    }
1435
113
    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
113
    buffer[w] = 0;       /* Terminate string */
1440
113
}
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
19.9k
{
1450
19.9k
    int base_filename_length = strlen(pdev->fname);
1451
1452
19.9k
#define REMOVE_TIF_FROM_BASENAME 1
1453
19.9k
#if REMOVE_TIF_FROM_BASENAME
1454
19.9k
    if (base_filename_length > 4 &&
1455
19.9k
        pdev->fname[base_filename_length - 4] == '.'  &&
1456
19.9k
        toupper(pdev->fname[base_filename_length - 3]) == 'T'  &&
1457
19.9k
        toupper(pdev->fname[base_filename_length - 2]) == 'I'  &&
1458
19.9k
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1459
0
        base_filename_length -= 4;
1460
0
        *double_f = false;
1461
0
    }
1462
19.9k
    else if (base_filename_length > 5 &&
1463
19.9k
        pdev->fname[base_filename_length - 5] == '.'  &&
1464
19.9k
        toupper(pdev->fname[base_filename_length - 4]) == 'T'  &&
1465
19.9k
        toupper(pdev->fname[base_filename_length - 3]) == 'I'  &&
1466
19.9k
        toupper(pdev->fname[base_filename_length - 2]) == 'F'  &&
1467
19.9k
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1468
19.9k
        base_filename_length -= 5;
1469
19.9k
        *double_f = true;
1470
19.9k
    }
1471
19.9k
#endif
1472
19.9k
#undef REMOVE_TIF_FROM_BASENAME
1473
1474
19.9k
    return base_filename_length;
1475
19.9k
}
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
19.9k
{
1484
19.9k
    bool double_f = false;
1485
19.9k
    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
20.1k
#define APPEND_TIF_TO_NAME 1
1492
20.1k
#define SUFFIX_SIZE (4 * APPEND_TIF_TO_NAME)
1493
1494
19.9k
    memcpy(buffer, pdev->fname, base_filename_length);
1495
19.9k
    buffer[base_filename_length++] = use_sep_name ? '(' : '.';
1496
19.9k
    buffer[base_filename_length] = 0;  /* terminate the string */
1497
1498
19.9k
    if (sep_num < pdev->devn_params.num_std_colorant_names) {
1499
19.8k
        if ((max_size - base_filename_length - 1) < strlen(pdev->devn_params.std_colorant_names[sep_num]))
1500
0
            return_error(gs_error_rangecheck);
1501
19.8k
        strcat(buffer, pdev->devn_params.std_colorant_names[sep_num]);
1502
19.8k
    }
1503
113
    else {
1504
113
        sep_num -= pdev->devn_params.num_std_colorant_names;
1505
113
        if (use_sep_name) {
1506
113
            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
113
            copy_separation_name(pdev, buffer + base_filename_length,
1509
113
                                max_size - SUFFIX_SIZE - 2 - base_filename_length, sep_num, 1);
1510
113
        } 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
113
    }
1517
19.9k
    if (use_sep_name)
1518
19.9k
        strcat(buffer, ")");
1519
1520
19.9k
#if APPEND_TIF_TO_NAME
1521
19.9k
    if (double_f) {
1522
19.9k
        if (max_size < strlen(buffer) + SUFFIX_SIZE + 1)
1523
0
            return_error(gs_error_rangecheck);
1524
19.9k
        strcat(buffer, ".tiff");
1525
19.9k
    }
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
19.9k
#endif
1532
19.9k
    return 0;
1533
19.9k
}
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.96k
{
1563
4.96k
    int num_comp =  num_std_colorants + num_spot;
1564
1565
4.96k
    if (num_comp > num_dev_comp)
1566
0
        num_comp = num_dev_comp;
1567
4.96k
    if (num_order)
1568
0
        num_comp = num_order;
1569
4.96k
    return num_comp;
1570
4.96k
}
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
26.2k
{
1582
26.2k
    int num_sep = pdev->devn_params.separations.num_separations;
1583
26.2k
    int num_std_colorants = pdev->devn_params.num_std_colorant_names;
1584
26.2k
    int sep_num;
1585
26.2k
    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
26.2k
    num_channels =
1591
26.2k
        ( (num_std_colorants + num_sep) < (GX_DEVICE_COLOR_MAX_COMPONENTS) ? (num_std_colorants + num_sep) : (GX_DEVICE_COLOR_MAX_COMPONENTS) );
1592
1593
131k
    for (sep_num = 0; sep_num < num_channels; sep_num++) {
1594
105k
        int comp_num = pdev->devn_params.separation_order_map[sep_num];
1595
1596
105k
        if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
1597
105k
            map_comp_to_sep[comp_num] = sep_num;
1598
105k
    }
1599
26.2k
}
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
6.87k
{
2437
6.87k
    tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
2438
6.87k
    int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
2439
6.87k
    int num_order = tfdev->devn_params.num_separation_order_names;
2440
6.87k
    int num_spot = tfdev->devn_params.separations.num_separations;
2441
6.87k
    int num_comp, comp_num, code = 0, code1 = 0;
2442
6.87k
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
2443
6.87k
    char *name = NULL;
2444
6.87k
    int save_depth = pdev->color_info.depth;
2445
6.87k
    int save_numcomps = pdev->color_info.num_components;
2446
6.87k
    int save_planes = pdev->num_planar_planes;
2447
6.87k
    const char *fmt;
2448
6.87k
    gs_parsed_file_name_t parsed;
2449
6.87k
    int non_encodable_count = 0;
2450
6.87k
    cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
2451
2452
6.87k
    name = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_print_page(name)");
2453
6.87k
    if (!name)
2454
0
        return_error(gs_error_VMerror);
2455
2456
6.87k
    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
6.87k
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
2467
6.87k
                                     strlen(tfdev->fname), pdev->memory);
2468
6.87k
    if (code < 0 || (fmt == NULL && tfdev->PageCount > 0)) {
2469
1.90k
       emprintf(tfdev->memory,
2470
1.90k
                "\nUse of the %%d format is required to output more than one page to tiffsep1.\n"
2471
1.90k
                "See doc/Devices.htm#TIFF for details.\n\n");
2472
1.90k
       code = gs_note_error(gs_error_ioerror);
2473
1.90k
       goto done;
2474
1.90k
    }
2475
    /* If the output file is on disk and the name contains a page #, */
2476
    /* then delete the previous file. */
2477
4.96k
    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.96k
    num_comp = number_output_separations(tfdev->color_info.num_components,
2509
4.96k
                                         num_std_colorants, num_order, num_spot);
2510
4.96k
    tfdev->page_num_comps = num_comp;
2511
2512
4.96k
    build_cmyk_map((gx_device *)tfdev, num_comp, &tfdev->equiv_cmyk_colors, cmyk_map);
2513
4.96k
    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
24.9k
    for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2520
19.9k
        int sep_num = map_comp_to_sep[comp_num];
2521
2522
19.9k
        code = create_separation_file_name((tiffsep_device *)tfdev, name,
2523
19.9k
                                        gp_file_name_sizeof, sep_num, true);
2524
19.9k
        if (code < 0) {
2525
0
            goto done;
2526
0
        }
2527
2528
        /* Open the separation file, if not already open */
2529
19.9k
        if (tfdev->sep_file[comp_num] == NULL) {
2530
19.9k
            code = gs_add_outputfile_control_path(tfdev->memory, name);
2531
19.9k
            if (code < 0) {
2532
0
                goto done;
2533
0
            }
2534
19.9k
            code = gx_device_open_output_file((gx_device *)pdev, name,
2535
19.9k
                    true, true, &(tfdev->sep_file[comp_num]));
2536
19.9k
            if (code < 0) {
2537
2
                goto done;
2538
2
            }
2539
19.9k
            tfdev->tiff[comp_num] = tiff_from_filep(pdev, name,
2540
19.9k
                                                    tfdev->sep_file[comp_num],
2541
19.9k
                                                    tfdev->BigEndian, tfdev->UseBigTIFF);
2542
19.9k
            if (!tfdev->tiff[comp_num]) {
2543
0
                code = gs_note_error(gs_error_ioerror);
2544
0
                goto done;
2545
0
            }
2546
19.9k
        }
2547
2548
19.9k
        pdev->color_info.depth = 1;
2549
19.9k
        pdev->color_info.num_components = 1;
2550
19.9k
        pdev->num_planar_planes = 1;
2551
19.9k
        code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num], 1, 0, tfdev->write_datetime);
2552
19.9k
        tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], 1, tfdev->Compression, tfdev->MaxStripSize);
2553
19.9k
        pdev->color_info.depth = save_depth;
2554
19.9k
        pdev->color_info.num_components = save_numcomps;
2555
19.9k
        pdev->num_planar_planes = save_planes;
2556
19.9k
        if (code < 0) {
2557
0
            goto done;
2558
0
        }
2559
2560
19.9k
    }   /* end initialization of separation files */
2561
2562
2563
4.96k
    {   /* Get the halftoned line and write out the separations */
2564
4.96k
        byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS];
2565
4.96k
        int width = tfdev->width;
2566
4.96k
        size_t raster_plane = bitmap_raster(width);
2567
4.96k
        int y;
2568
4.96k
        gs_get_bits_params_t params;
2569
4.96k
        gs_int_rect rect;
2570
2571
        /* the line is assumed to be 32-bit aligned by the alloc */
2572
4.96k
        memset(planes, 0, sizeof(*planes) * GS_CLIENT_COLOR_MAX_COMPONENTS);
2573
2574
        /* Return planar data */
2575
4.96k
        params.options = (GB_RETURN_POINTER | GB_RETURN_COPY |
2576
4.96k
             GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
2577
4.96k
             GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE);
2578
4.96k
        params.x_offset = 0;
2579
4.96k
        params.raster = bitmap_raster(width * pdev->color_info.depth);
2580
2581
4.96k
        code = 0;
2582
24.9k
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2583
19.9k
            planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane,
2584
19.9k
                                            "tiffsep1_print_page");
2585
19.9k
            if (planes[comp_num] == NULL) {
2586
0
                code = gs_error_VMerror;
2587
0
                break;
2588
0
            }
2589
19.9k
        }
2590
2591
24.9k
        for (comp_num = 0; comp_num < num_comp; comp_num++ )
2592
19.9k
            TIFFCheckpointDirectory(tfdev->tiff[comp_num]);
2593
2594
4.96k
        rect.p.x = 0;
2595
4.96k
        rect.q.x = pdev->width;
2596
        /* Loop for the lines */
2597
8.32M
        for (y = 0; y < pdev->height; ++y) {
2598
8.32M
            rect.p.y = y;
2599
8.32M
            rect.q.y = y + 1;
2600
            /* We have to reset the pointers since get_bits_rect will have moved them */
2601
41.7M
            for (comp_num = 0; comp_num < num_comp; comp_num++)
2602
33.4M
                params.data[comp_num] = planes[comp_num];
2603
8.32M
            code = (*dev_proc(pdev, get_bits_rectangle))((gx_device *)pdev, &rect, &params);
2604
8.32M
            if (code < 0)
2605
1
                break;
2606
2607
            /* write it out */
2608
41.7M
            for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2609
33.4M
                int i;
2610
33.4M
                byte *src = params.data[comp_num];
2611
2612
                /* TIFF 1-bit is additive, invert the data */
2613
7.46G
                for (i=0; i<raster_plane; i++)
2614
7.42G
                    *src++ ^= 0xff;   /* invert the data */
2615
33.4M
                src = params.data[comp_num];
2616
33.4M
                TIFFWriteScanline(tfdev->tiff[comp_num], src, y, 0);
2617
33.4M
            } /* 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
8.32M
        }
2675
        /* Update the strip data */
2676
24.9k
        for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2677
19.9k
            TIFFWriteDirectory(tfdev->tiff[comp_num]);
2678
19.9k
            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
19.9k
        }
2694
4.96k
        code = code1;
2695
2696
        /* free any allocations and exit with code */
2697
24.9k
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2698
19.9k
            gs_free_object(pdev->memory, planes[comp_num], "tiffsep1_print_page");
2699
19.9k
        }
2700
4.96k
    }
2701
    /*
2702
     * If we have any non encodable pixels then signal an error.
2703
     */
2704
4.96k
    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
6.87k
done:
2710
6.87k
    if (name)
2711
6.87k
        gs_free_object(pdev->memory, name, "tiffsep1_print_page(name)");
2712
6.87k
    return code;
2713
4.96k
}
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
38.3M
{
2721
38.3M
    gx_color_index color = 0;
2722
38.3M
    int i = 0;
2723
38.3M
    int ncomp = dev->color_info.num_components;
2724
2725
211M
    for (; i < ncomp; i++) {
2726
173M
        color <<= 1;
2727
173M
        color |= colors[i] == gx_max_color_value;
2728
173M
    }
2729
38.3M
    return (color == gx_no_color_index ? color ^ 1 : color);
2730
38.3M
}
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
}