Coverage Report

Created: 2025-06-10 06:49

/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
0
{
319
0
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
320
0
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
321
0
    TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
322
0
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
323
324
0
    tiff_set_compression(pdev, tif, compression, max_strip_size);
325
0
}
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
0
{
538
0
    if (op == gxdso_supports_iccpostrender || op == gxdso_supports_devn
539
0
     || op == gxdso_skip_icc_component_validation) {
540
0
        return true;
541
0
    }
542
0
    return gdev_prn_dev_spec_op(dev_, op, data, datasize);
543
0
}
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
0
ENUM_PTRS_WITH(tiffsep_device_enum_ptrs, tiffsep_device *pdev)
698
0
{
699
0
    if (index < pdev->devn_params.separations.num_separations)
700
0
        ENUM_RETURN(pdev->devn_params.separations.names[index].data);
701
0
    ENUM_PREFIX(st_device_printer,
702
0
                    pdev->devn_params.separations.num_separations);
703
0
    return 0;
704
0
}
705
0
ENUM_PTRS_END
706
707
0
static RELOC_PTRS_WITH(tiffsep_device_reloc_ptrs, tiffsep_device *pdev)
708
0
{
709
0
    RELOC_PREFIX(st_device_printer);
710
0
    {
711
0
        int i;
712
713
0
        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
0
    }
717
0
}
718
0
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
0
{
726
    /* We need to deallocate the names. */
727
0
    devn_free_params((gx_device*) vpdev);
728
0
    gx_device_finalize(cmem, vpdev);
729
0
}
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
0
{
738
0
    gdev_prn_initialize_device_procs(dev);
739
740
0
    set_dev_proc(dev, output_page, gdev_prn_output_page_seekable);
741
0
    set_dev_proc(dev, open_device, tiffsep_prn_open);
742
0
    set_dev_proc(dev, close_device, tiffsep_prn_close);
743
0
    set_dev_proc(dev, map_color_rgb, tiffsep_decode_color);
744
0
    set_dev_proc(dev, get_params, tiffsep_get_params);
745
0
    set_dev_proc(dev, put_params, tiffsep_put_params);
746
0
    set_dev_proc(dev, get_color_mapping_procs, tiffsep_get_color_mapping_procs);
747
0
    set_dev_proc(dev, get_color_comp_index, tiffsep_get_color_comp_index);
748
0
    set_dev_proc(dev, encode_color, tiffsep_encode_color);
749
0
    set_dev_proc(dev, decode_color, tiffsep_decode_color);
750
0
    set_dev_proc(dev, update_spot_equivalent_colors, tiffsep_update_spot_equivalent_colors);
751
0
    set_dev_proc(dev, ret_devn_params, tiffsep_ret_devn_params);
752
0
    set_dev_proc(dev, dev_spec_op, tiffsep_spec_op);
753
0
}
754
755
static void
756
tiffsep1_initialize_device_procs(gx_device *dev)
757
0
{
758
0
    tiffsep_initialize_device_procs(dev);
759
0
    set_dev_proc(dev, open_device, tiffsep1_prn_open);
760
0
    set_dev_proc(dev, close_device, tiffsep1_prn_close);
761
0
    set_dev_proc(dev, encode_color, tiffsep1_encode_color);
762
0
    set_dev_proc(dev, decode_color, tiffsep1_decode_color);
763
0
    set_dev_proc(dev, map_color_rgb, cmyk_1bit_map_color_rgb);
764
0
}
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
0
{
846
0
    int * map = ((tiffsep_device *) dev)->devn_params.separation_order_map;
847
848
0
    gray_cs_to_devn_cm(dev, map, gray, out);
849
0
}
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
0
{
864
0
    const gs_devn_params *devn = tiffsep_ret_devn_params_const(dev);
865
0
    const int *map = devn->separation_order_map;
866
0
    int j;
867
868
0
    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
0
    } else {
893
0
        cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
894
0
    }
895
0
}
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
0
{
910
0
    *tdev = dev;
911
0
    return &tiffsep_cm_procs;
912
0
}
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
0
{
961
0
    tiffsep_device * pdev = (tiffsep_device *)dev;
962
963
0
    update_spot_equivalent_cmyk_colors(dev, pgs, pcs,
964
0
                    &pdev->devn_params, &pdev->equiv_cmyk_colors);
965
0
    return 0;
966
0
}
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
0
{
974
0
    tiffsep_device * pdev = (tiffsep_device *)dev;
975
976
0
    return &pdev->devn_params;
977
0
}
978
979
static const gs_devn_params *
980
tiffsep_ret_devn_params_const (const gx_device * dev)
981
0
{
982
0
    const tiffsep_device * pdev = (const tiffsep_device *)dev;
983
984
0
    return &pdev->devn_params;
985
0
}
986
987
/* Get parameters.  We provide a default CRD. */
988
static int
989
tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
990
0
{
991
0
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
992
0
    int code = gdev_prn_get_params(pdev, plist);
993
0
    int ecode = code;
994
0
    gs_param_string comprstr;
995
996
0
    if (code < 0)
997
0
        return code;
998
999
0
    code = devn_get_params(pdev, plist,
1000
0
                &(((tiffsep_device *)pdev)->devn_params),
1001
0
                &(((tiffsep_device *)pdev)->equiv_cmyk_colors));
1002
0
    if (code < 0)
1003
0
        return code;
1004
1005
0
    if ((code = param_write_bool(plist, "NoSeparationFiles", &pdevn->NoSeparationFiles)) < 0)
1006
0
        ecode = code;
1007
0
    if ((code = param_write_bool(plist, "BigEndian", &pdevn->BigEndian)) < 0)
1008
0
        ecode = code;
1009
0
    if ((code = param_write_bool(plist, "TIFFDateTime", &pdevn->write_datetime)) < 0)
1010
0
        ecode = code;
1011
0
    if ((code = tiff_compression_param_string(&comprstr, pdevn->Compression)) < 0 ||
1012
0
        (code = param_write_string(plist, "Compression", &comprstr)) < 0)
1013
0
        ecode = code;
1014
0
    if ((code = param_write_long(plist, "MaxStripSize", &pdevn->MaxStripSize)) < 0)
1015
0
        ecode = code;
1016
0
    if ((code = param_write_long(plist, "BitsPerComponent", &pdevn->BitsPerComponent)) < 0)
1017
0
        ecode = code;
1018
0
    if ((code = param_write_int(plist, "MaxSpots", &pdevn->max_spots)) < 0)
1019
0
        ecode = code;
1020
0
    if ((code = param_write_bool(plist, "LockColorants", &pdevn->lock_colorants)) < 0)
1021
0
        ecode = code;
1022
0
    if ((code = param_write_bool(plist, "PrintSpotCMYK", &pdevn->PrintSpotCMYK)) < 0)
1023
0
        ecode = code;
1024
0
    if ((code = gx_downscaler_write_params(plist, &pdevn->downscale,
1025
0
                                           GX_DOWNSCALER_PARAMS_MFS |
1026
0
                                           GX_DOWNSCALER_PARAMS_TRAP)) < 0)
1027
0
        ecode = code;
1028
1029
0
    return ecode;
1030
0
}
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
0
{
1036
0
    tiffsep_device * const pdevn = (tiffsep_device *) pdev;
1037
0
    int code;
1038
0
    const char *param_name;
1039
0
    gs_param_string comprstr;
1040
0
    long bpc = pdevn->BitsPerComponent;
1041
0
    int max_spots = pdevn->max_spots;
1042
1043
0
    switch (code = param_read_bool(plist, (param_name = "NoSeparationFiles"),
1044
0
        &pdevn->NoSeparationFiles)) {
1045
0
    default:
1046
0
        param_signal_error(plist, param_name, code);
1047
0
        return code;
1048
0
    case 0:
1049
0
    case 1:
1050
0
        break;
1051
0
    }
1052
    /* Read BigEndian option as bool */
1053
0
    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
0
        case 0:
1058
0
        case 1:
1059
0
            break;
1060
0
    }
1061
0
    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
0
        case 0:
1065
0
        case 1:
1066
0
            break;
1067
0
    }
1068
0
    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
0
        case 0:
1073
0
        case 1:
1074
0
            break;
1075
0
    }
1076
1077
0
    switch (code = param_read_long(plist, (param_name = "BitsPerComponent"), &bpc)) {
1078
0
        case 0:
1079
0
            if ((bpc == 1) || (bpc == 8)) {
1080
0
                pdevn->BitsPerComponent = bpc;
1081
0
                break;
1082
0
            }
1083
0
            code = gs_error_rangecheck;
1084
0
        default:
1085
0
            param_signal_error(plist, param_name, code);
1086
0
            return code;
1087
0
        case 1:
1088
0
            break;
1089
0
    }
1090
1091
    /* Read Compression */
1092
0
    switch (code = param_read_string(plist, (param_name = "Compression"), &comprstr)) {
1093
0
        case 0:
1094
0
            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
0
            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
0
            break;
1108
0
        case 1:
1109
0
            break;
1110
0
        default:
1111
0
            param_signal_error(plist, param_name, code);
1112
0
            return code;
1113
0
    }
1114
0
    switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &pdevn->MaxStripSize)) {
1115
0
        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
0
            if (pdevn->MaxStripSize >= 0)
1122
0
                break;
1123
0
            code = gs_error_rangecheck;
1124
0
        default:
1125
0
            param_signal_error(plist, param_name, code);
1126
0
            return code;
1127
0
        case 1:
1128
0
            break;
1129
0
    }
1130
0
    switch (code = param_read_bool(plist, (param_name = "LockColorants"),
1131
0
            &(pdevn->lock_colorants))) {
1132
0
        case 0:
1133
0
            break;
1134
0
        case 1:
1135
0
            break;
1136
0
        default:
1137
0
            param_signal_error(plist, param_name, code);
1138
0
            return code;
1139
0
    }
1140
0
    switch (code = param_read_int(plist, (param_name = "MaxSpots"), &max_spots)) {
1141
0
        case 0:
1142
0
            if ((max_spots >= 0) && (max_spots <= GS_CLIENT_COLOR_MAX_COMPONENTS-4)) {
1143
0
                pdevn->max_spots = max_spots;
1144
0
                break;
1145
0
            }
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
0
        case 1:
1150
0
            break;
1151
0
        default:
1152
0
            param_signal_error(plist, param_name, code);
1153
0
            return code;
1154
0
    }
1155
1156
0
    code = gx_downscaler_read_params(plist, &pdevn->downscale,
1157
0
                                     GX_DOWNSCALER_PARAMS_MFS | GX_DOWNSCALER_PARAMS_TRAP);
1158
0
    if (code < 0)
1159
0
        return code;
1160
1161
0
    code = devn_printer_put_params(pdev, plist,
1162
0
                &(pdevn->devn_params), &(pdevn->equiv_cmyk_colors));
1163
1164
0
    return(code);
1165
0
}
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
0
{
1176
0
    gx_device_printer *ppdev = (gx_device_printer *)pdev;
1177
0
    tiffsep1_device *pdev_sep = (tiffsep1_device *) pdev;
1178
0
    int code, k;
1179
1180
    /* Use our own warning and error message handlers in libtiff */
1181
0
    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
0
    pdev_sep->warning_given = false;
1186
0
    if (pdev_sep->devn_params.page_spot_colors >= 0) {
1187
0
        pdev->color_info.num_components =
1188
0
            (pdev_sep->devn_params.page_spot_colors
1189
0
                                 + pdev_sep->devn_params.num_std_colorant_names);
1190
0
        if (pdev->color_info.num_components > pdev->color_info.max_components)
1191
0
            pdev->color_info.num_components = pdev->color_info.max_components;
1192
0
    } 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
0
        int num_comp = pdev_sep->max_spots + 4; /* Spots + CMYK */
1199
0
        if (num_comp > GS_CLIENT_COLOR_MAX_COMPONENTS)
1200
0
            num_comp = GS_CLIENT_COLOR_MAX_COMPONENTS;
1201
0
        pdev->color_info.num_components = num_comp;
1202
0
        pdev->color_info.max_components = num_comp;
1203
0
    }
1204
    /* Push this to the max amount as a default if someone has not set it */
1205
0
    if (pdev_sep->devn_params.num_separation_order_names == 0)
1206
0
        for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
1207
0
            pdev_sep->devn_params.separation_order_map[k] = k;
1208
0
        }
1209
0
    pdev->color_info.depth = bpc_to_depth(pdev->color_info.num_components,
1210
0
                                          pdev_sep->devn_params.bitspercomponent);
1211
0
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
1212
0
    code = gdev_prn_open_planar(pdev, pdev->color_info.num_components);
1213
0
    while (pdev->child)
1214
0
        pdev = pdev->child;
1215
0
    ppdev = (gx_device_printer *)pdev;
1216
0
    pdev_sep = (tiffsep1_device *)pdev;
1217
1218
0
    ppdev->file = NULL;
1219
0
    pdev->icc_struct->supports_devn = true;
1220
1221
0
    return code;
1222
0
}
1223
1224
/* Close the tiffsep device */
1225
int
1226
tiffsep1_prn_close(gx_device * pdev)
1227
0
{
1228
0
    tiffsep1_device * const tfdev = (tiffsep1_device *) pdev;
1229
0
    char *name= NULL;
1230
0
    int code = gdev_prn_close(pdev);
1231
0
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
1232
0
    int comp_num;
1233
0
    const char *fmt;
1234
0
    gs_parsed_file_name_t parsed;
1235
1236
0
    if (code < 0)
1237
0
        return code;
1238
1239
0
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
1240
0
                                     strlen(tfdev->fname), pdev->memory);
1241
0
    if (code < 0) {
1242
0
        goto done;
1243
0
    }
1244
1245
0
#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
0
    if (parsed.iodev == iodev_default(pdev->memory)) {          /* filename includes "%nnd" */
1248
0
        char *compname = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_prn_close(compname)");
1249
0
        if (!compname) {
1250
0
            code = gs_note_error(gs_error_VMerror);
1251
0
            goto done;
1252
0
        }
1253
1254
0
        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
0
        } else {
1265
0
            parsed.iodev->procs.delete_file(parsed.iodev, tfdev->fname);
1266
0
        }
1267
0
        gs_free_object(pdev->memory, compname, "tiffsep1_prn_close(compname)");
1268
0
    }
1269
0
#endif
1270
1271
0
    build_comp_to_sep_map((tiffsep_device *)tfdev, map_comp_to_sep);
1272
    /* Close the separation files */
1273
0
    for (comp_num = 0; comp_num < tfdev->page_num_comps; comp_num++ ) {
1274
0
        const char *lname_empty = "";
1275
0
        char *lname = NULL;
1276
1277
0
        if (tfdev->tiff[comp_num] != NULL) {
1278
0
            tiff_filename_from_tiff(tfdev->tiff[comp_num], &name);
1279
0
        }
1280
0
        else {
1281
0
            name = (char *)lname_empty;
1282
0
        }
1283
1284
0
        lname = (char *)gs_alloc_bytes(tfdev->memory, strlen(name) + 1, "tiffsep1_prn_close");
1285
0
        if (lname == NULL) {
1286
0
            code = gs_note_error(gs_error_VMerror);
1287
0
            goto done;
1288
0
        }
1289
0
        memcpy(lname, name, strlen(name) + 1);
1290
1291
0
        if (tfdev->tiff[comp_num]) {
1292
0
            void *t = TIFFClientdata(tfdev->tiff[comp_num]);
1293
1294
0
            TIFFCleanup(tfdev->tiff[comp_num]);
1295
0
            gs_free(pdev->memory, t, sizeof(tifs_io_private), 1, "tiffsep1_prn_close");
1296
0
            tfdev->tiff[comp_num] = NULL;
1297
0
        }
1298
0
        if (tfdev->sep_file[comp_num] != NULL) {
1299
0
            code = gx_device_close_output_file(pdev, lname, tfdev->sep_file[comp_num]);
1300
0
            if (code >= 0)
1301
0
                code = gs_remove_outputfile_control_path(pdev->memory, lname);
1302
0
            if (code < 0) {
1303
0
                goto done;
1304
0
            }
1305
0
            tfdev->sep_file[comp_num] = NULL;
1306
0
        }
1307
0
        gs_free_object(tfdev->memory, lname, "tiffsep1_prn_close");
1308
0
    }
1309
1310
0
done:
1311
0
    return code;
1312
0
}
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
0
{
1332
0
    tiffsep_device * pdev = (tiffsep_device *) dev;
1333
0
    int index;
1334
1335
0
    if (strncmp(pname, "None", name_size) == 0) return -1;
1336
0
    index = devn_get_color_comp_index(dev,
1337
0
                &(pdev->devn_params), &(pdev->equiv_cmyk_colors),
1338
0
                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
0
    if (index < 0 && component_type == SEPARATION_NAME &&
1346
0
        pdev->warning_given == false &&
1347
0
        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
0
    return index;
1354
0
}
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
0
{
1370
0
    int sep_size = pdev->devn_params.separations.names[sep_num].size;
1371
0
    const byte *p = pdev->devn_params.separations.names[sep_num].data;
1372
0
    int r, w, use_sep_num = 0;
1373
0
    const char *stdnames[4] = {"CYAN", "MAGENTA", "YELLOW", "BLACK"};
1374
0
    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
0
    for (r=0;r<4;r++)
1385
0
    {
1386
0
        if (strlen(stdnames[r]) == pdev->devn_params.separations.names[sep_num].size) {
1387
0
            use_sep_num = 1;
1388
0
            for (w=0;w<strlen(stdnames[r]);w++) {
1389
0
                if (toupper(pdev->devn_params.separations.names[sep_num].data[w]) != stdnames[r][w]) {
1390
0
                    use_sep_num = 0;
1391
0
                    break;
1392
0
                }
1393
0
            }
1394
0
        }
1395
0
    }
1396
0
    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
0
    r = 0;
1404
0
    w = 0;
1405
0
    while (r < sep_size && w < max_size-1 - strlen(sep_num_str))
1406
0
    {
1407
0
        int c = p[r++];
1408
0
        if (c >= 127 ||
1409
0
            !gp_file_name_good_char(c) ||
1410
0
            c == '%')
1411
0
        {
1412
            /* Top bit set, backspace, or char we can't represent on the
1413
             * filesystem. */
1414
0
            if (w + 2 + escape >= max_size-1 - strlen(sep_num_str))
1415
0
                break;
1416
0
            buffer[w++] = '%';
1417
0
            if (escape)
1418
0
                buffer[w++] = '%';
1419
0
            buffer[w++] = "0123456789ABCDEF"[c>>4];
1420
0
            buffer[w++] = "0123456789ABCDEF"[c&15];
1421
0
        }
1422
0
        else
1423
0
        {
1424
0
            buffer[w++] = c;
1425
0
        }
1426
0
    }
1427
0
    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
0
    buffer[w] = 0;       /* Terminate string */
1432
0
}
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
0
{
1442
0
    int base_filename_length = strlen(pdev->fname);
1443
1444
0
#define REMOVE_TIF_FROM_BASENAME 1
1445
0
#if REMOVE_TIF_FROM_BASENAME
1446
0
    if (base_filename_length > 4 &&
1447
0
        pdev->fname[base_filename_length - 4] == '.'  &&
1448
0
        toupper(pdev->fname[base_filename_length - 3]) == 'T'  &&
1449
0
        toupper(pdev->fname[base_filename_length - 2]) == 'I'  &&
1450
0
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1451
0
        base_filename_length -= 4;
1452
0
        *double_f = false;
1453
0
    }
1454
0
    else if (base_filename_length > 5 &&
1455
0
        pdev->fname[base_filename_length - 5] == '.'  &&
1456
0
        toupper(pdev->fname[base_filename_length - 4]) == 'T'  &&
1457
0
        toupper(pdev->fname[base_filename_length - 3]) == 'I'  &&
1458
0
        toupper(pdev->fname[base_filename_length - 2]) == 'F'  &&
1459
0
        toupper(pdev->fname[base_filename_length - 1]) == 'F') {
1460
0
        base_filename_length -= 5;
1461
0
        *double_f = true;
1462
0
    }
1463
0
#endif
1464
0
#undef REMOVE_TIF_FROM_BASENAME
1465
1466
0
    return base_filename_length;
1467
0
}
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
0
{
1476
0
    bool double_f = false;
1477
0
    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
0
#define APPEND_TIF_TO_NAME 1
1484
0
#define SUFFIX_SIZE (4 * APPEND_TIF_TO_NAME)
1485
1486
0
    memcpy(buffer, pdev->fname, base_filename_length);
1487
0
    buffer[base_filename_length++] = use_sep_name ? '(' : '.';
1488
0
    buffer[base_filename_length] = 0;  /* terminate the string */
1489
1490
0
    if (sep_num < pdev->devn_params.num_std_colorant_names) {
1491
0
        if ((max_size - base_filename_length - 1) < strlen(pdev->devn_params.std_colorant_names[sep_num]))
1492
0
            return_error(gs_error_rangecheck);
1493
0
        strcat(buffer, pdev->devn_params.std_colorant_names[sep_num]);
1494
0
    }
1495
0
    else {
1496
0
        sep_num -= pdev->devn_params.num_std_colorant_names;
1497
0
        if (use_sep_name) {
1498
0
            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
0
            copy_separation_name(pdev, buffer + base_filename_length,
1501
0
                                max_size - SUFFIX_SIZE - 2 - base_filename_length, sep_num, 1);
1502
0
        } 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
0
    }
1509
0
    if (use_sep_name)
1510
0
        strcat(buffer, ")");
1511
1512
0
#if APPEND_TIF_TO_NAME
1513
0
    if (double_f) {
1514
0
        if (max_size < strlen(buffer) + SUFFIX_SIZE + 1)
1515
0
            return_error(gs_error_rangecheck);
1516
0
        strcat(buffer, ".tiff");
1517
0
    }
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
0
#endif
1524
0
    return 0;
1525
0
}
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
0
{
1555
0
    int num_comp =  num_std_colorants + num_spot;
1556
1557
0
    if (num_comp > num_dev_comp)
1558
0
        num_comp = num_dev_comp;
1559
0
    if (num_order)
1560
0
        num_comp = num_order;
1561
0
    return num_comp;
1562
0
}
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
0
{
1574
0
    int num_sep = pdev->devn_params.separations.num_separations;
1575
0
    int num_std_colorants = pdev->devn_params.num_std_colorant_names;
1576
0
    int sep_num;
1577
0
    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
0
    num_channels =
1583
0
        ( (num_std_colorants + num_sep) < (GX_DEVICE_COLOR_MAX_COMPONENTS) ? (num_std_colorants + num_sep) : (GX_DEVICE_COLOR_MAX_COMPONENTS) );
1584
1585
0
    for (sep_num = 0; sep_num < num_channels; sep_num++) {
1586
0
        int comp_num = pdev->devn_params.separation_order_map[sep_num];
1587
1588
0
        if (comp_num >= 0 && comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS)
1589
0
            map_comp_to_sep[comp_num] = sep_num;
1590
0
    }
1591
0
}
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
0
{
2429
0
    tiffsep1_device * const tfdev = (tiffsep1_device *)pdev;
2430
0
    int num_std_colorants = tfdev->devn_params.num_std_colorant_names;
2431
0
    int num_order = tfdev->devn_params.num_separation_order_names;
2432
0
    int num_spot = tfdev->devn_params.separations.num_separations;
2433
0
    int num_comp, comp_num, code = 0, code1 = 0;
2434
0
    short map_comp_to_sep[GX_DEVICE_COLOR_MAX_COMPONENTS];
2435
0
    char *name = NULL;
2436
0
    int save_depth = pdev->color_info.depth;
2437
0
    int save_numcomps = pdev->color_info.num_components;
2438
0
    int save_planes = pdev->num_planar_planes;
2439
0
    const char *fmt;
2440
0
    gs_parsed_file_name_t parsed;
2441
0
    int non_encodable_count = 0;
2442
0
    cmyk_composite_map cmyk_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
2443
2444
0
    name = (char *)gs_alloc_bytes(pdev->memory, gp_file_name_sizeof, "tiffsep1_print_page(name)");
2445
0
    if (!name)
2446
0
        return_error(gs_error_VMerror);
2447
2448
0
    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
0
    code = gx_parse_output_file_name(&parsed, &fmt, tfdev->fname,
2459
0
                                     strlen(tfdev->fname), pdev->memory);
2460
0
    if (code < 0 || (fmt == NULL && tfdev->PageCount > 0)) {
2461
0
       emprintf(tfdev->memory,
2462
0
                "\nUse of the %%d format is required to output more than one page to tiffsep1.\n"
2463
0
                "See doc/Devices.htm#TIFF for details.\n\n");
2464
0
       code = gs_note_error(gs_error_ioerror);
2465
0
       goto done;
2466
0
    }
2467
    /* If the output file is on disk and the name contains a page #, */
2468
    /* then delete the previous file. */
2469
0
    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
0
    num_comp = number_output_separations(tfdev->color_info.num_components,
2501
0
                                         num_std_colorants, num_order, num_spot);
2502
0
    tfdev->page_num_comps = num_comp;
2503
2504
0
    build_cmyk_map((gx_device *)tfdev, num_comp, &tfdev->equiv_cmyk_colors, cmyk_map);
2505
0
    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
0
    for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2512
0
        int sep_num = map_comp_to_sep[comp_num];
2513
2514
0
        code = create_separation_file_name((tiffsep_device *)tfdev, name,
2515
0
                                        gp_file_name_sizeof, sep_num, true);
2516
0
        if (code < 0) {
2517
0
            goto done;
2518
0
        }
2519
2520
        /* Open the separation file, if not already open */
2521
0
        if (tfdev->sep_file[comp_num] == NULL) {
2522
0
            code = gs_add_outputfile_control_path(tfdev->memory, name);
2523
0
            if (code < 0) {
2524
0
                goto done;
2525
0
            }
2526
0
            code = gx_device_open_output_file((gx_device *)pdev, name,
2527
0
                    true, true, &(tfdev->sep_file[comp_num]));
2528
0
            if (code < 0) {
2529
0
                goto done;
2530
0
            }
2531
0
            tfdev->tiff[comp_num] = tiff_from_filep(pdev, name,
2532
0
                                                    tfdev->sep_file[comp_num],
2533
0
                                                    tfdev->BigEndian, tfdev->UseBigTIFF);
2534
0
            if (!tfdev->tiff[comp_num]) {
2535
0
                code = gs_note_error(gs_error_ioerror);
2536
0
                goto done;
2537
0
            }
2538
0
        }
2539
2540
0
        pdev->color_info.depth = 1;
2541
0
        pdev->color_info.num_components = 1;
2542
0
        pdev->num_planar_planes = 1;
2543
0
        code = tiff_set_fields_for_printer(pdev, tfdev->tiff[comp_num], 1, 0, tfdev->write_datetime);
2544
0
        tiff_set_gray_fields(pdev, tfdev->tiff[comp_num], 1, tfdev->Compression, tfdev->MaxStripSize);
2545
0
        pdev->color_info.depth = save_depth;
2546
0
        pdev->color_info.num_components = save_numcomps;
2547
0
        pdev->num_planar_planes = save_planes;
2548
0
        if (code < 0) {
2549
0
            goto done;
2550
0
        }
2551
2552
0
    }   /* end initialization of separation files */
2553
2554
2555
0
    {   /* Get the halftoned line and write out the separations */
2556
0
        byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS];
2557
0
        int width = tfdev->width;
2558
0
        int raster_plane = bitmap_raster(width);
2559
0
        int y;
2560
0
        gs_get_bits_params_t params;
2561
0
        gs_int_rect rect;
2562
2563
        /* the line is assumed to be 32-bit aligned by the alloc */
2564
0
        memset(planes, 0, sizeof(*planes) * GS_CLIENT_COLOR_MAX_COMPONENTS);
2565
2566
        /* Return planar data */
2567
0
        params.options = (GB_RETURN_POINTER | GB_RETURN_COPY |
2568
0
             GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
2569
0
             GB_PACKING_PLANAR | GB_COLORS_NATIVE | GB_ALPHA_NONE);
2570
0
        params.x_offset = 0;
2571
0
        params.raster = bitmap_raster(width * pdev->color_info.depth);
2572
2573
0
        code = 0;
2574
0
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2575
0
            planes[comp_num] = gs_alloc_bytes(pdev->memory, raster_plane,
2576
0
                                            "tiffsep1_print_page");
2577
0
            if (planes[comp_num] == NULL) {
2578
0
                code = gs_error_VMerror;
2579
0
                break;
2580
0
            }
2581
0
        }
2582
2583
0
        for (comp_num = 0; comp_num < num_comp; comp_num++ )
2584
0
            TIFFCheckpointDirectory(tfdev->tiff[comp_num]);
2585
2586
0
        rect.p.x = 0;
2587
0
        rect.q.x = pdev->width;
2588
        /* Loop for the lines */
2589
0
        for (y = 0; y < pdev->height; ++y) {
2590
0
            rect.p.y = y;
2591
0
            rect.q.y = y + 1;
2592
            /* We have to reset the pointers since get_bits_rect will have moved them */
2593
0
            for (comp_num = 0; comp_num < num_comp; comp_num++)
2594
0
                params.data[comp_num] = planes[comp_num];
2595
0
            code = (*dev_proc(pdev, get_bits_rectangle))((gx_device *)pdev, &rect, &params);
2596
0
            if (code < 0)
2597
0
                break;
2598
2599
            /* write it out */
2600
0
            for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2601
0
                int i;
2602
0
                byte *src = params.data[comp_num];
2603
2604
                /* TIFF 1-bit is additive, invert the data */
2605
0
                for (i=0; i<raster_plane; i++)
2606
0
                    *src++ ^= 0xff;   /* invert the data */
2607
0
                src = params.data[comp_num];
2608
0
                TIFFWriteScanline(tfdev->tiff[comp_num], src, y, 0);
2609
0
            } /* 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
0
        }
2667
        /* Update the strip data */
2668
0
        for (comp_num = 0; comp_num < num_comp; comp_num++ ) {
2669
0
            TIFFWriteDirectory(tfdev->tiff[comp_num]);
2670
0
            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
0
        }
2686
0
        code = code1;
2687
2688
        /* free any allocations and exit with code */
2689
0
        for (comp_num = 0; comp_num < num_comp; comp_num++) {
2690
0
            gs_free_object(pdev->memory, planes[comp_num], "tiffsep1_print_page");
2691
0
        }
2692
0
    }
2693
    /*
2694
     * If we have any non encodable pixels then signal an error.
2695
     */
2696
0
    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
0
done:
2702
0
    if (name)
2703
0
        gs_free_object(pdev->memory, name, "tiffsep1_print_page(name)");
2704
0
    return code;
2705
0
}
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
0
{
2713
0
    gx_color_index color = 0;
2714
0
    int i = 0;
2715
0
    int ncomp = dev->color_info.num_components;
2716
2717
0
    for (; i < ncomp; i++) {
2718
0
        color <<= 1;
2719
0
        color |= colors[i] == gx_max_color_value;
2720
0
    }
2721
0
    return (color == gx_no_color_index ? color ^ 1 : color);
2722
0
}
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
}