Coverage Report

Created: 2025-06-24 07:01

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