Coverage Report

Created: 2025-04-22 06:20

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