Coverage Report

Created: 2025-08-28 07:06

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