Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/gdevtifs.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* TIFF-writing substructure */
18
19
#include "stdint_.h"   /* for tiff.h */
20
#include "stdio_.h"
21
#include "time_.h"
22
#include "gdevtifs.h"
23
#include "gstypes.h"
24
#include "gscdefs.h"
25
#include "gdevprn.h"
26
#include "minftrsz.h"
27
#include "gxdownscale.h"
28
#include "scommon.h"
29
#include "stream.h"
30
#include "strmio.h"
31
#include "gsicc_cache.h"
32
#include "gscms.h"
33
#include "gstiffio.h"
34
#include "gdevkrnlsclass.h" /* 'standard' built in subclasses, currently First/Last Page and obejct filter */
35
36
int
37
tiff_open(gx_device *pdev)
38
0
{
39
0
    gx_device_printer *ppdev = (gx_device_printer *)pdev;
40
0
    int code;
41
0
    bool update_procs = false;
42
43
    /* Use our own warning and error message handlers in libtiff */
44
0
    tiff_set_handlers();
45
46
0
    code = install_internal_subclass_devices((gx_device **)&pdev, &update_procs);
47
0
    if (code < 0)
48
0
        return code;
49
    /* If we've been subclassed, find the terminal device */
50
0
    while(pdev->child)
51
0
        pdev = pdev->child;
52
0
    ppdev = (gx_device_printer *)pdev;
53
54
0
    ppdev->file = NULL;
55
0
    code = gdev_prn_allocate_memory(pdev, NULL, 0, 0);
56
0
    if (code < 0)
57
0
        return code;
58
0
    if (update_procs) {
59
0
        if (pdev->ObjectHandlerPushed) {
60
0
            gx_copy_device_procs(pdev->parent, pdev, &gs_obj_filter_device);
61
0
            pdev = pdev->parent;
62
0
        }
63
0
        if (pdev->PageHandlerPushed)
64
0
            gx_copy_device_procs(pdev->parent, pdev, &gs_flp_device);
65
0
    }
66
0
    if (ppdev->OpenOutputFile)
67
0
        code = gdev_prn_open_printer_seekable(pdev, 1, true);
68
0
    return code;
69
0
}
70
71
int
72
tiff_close(gx_device * pdev)
73
0
{
74
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
75
76
0
    if (tfdev->tif)
77
0
        TIFFClose(tfdev->tif);
78
79
0
    gsicc_free_link_dev(tfdev->icclink);
80
0
    tfdev->icclink = NULL;
81
82
0
    return gdev_prn_close(pdev);
83
0
}
84
85
static int
86
tiff_get_some_params(gx_device * dev, gs_param_list * plist, int which)
87
0
{
88
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)dev;
89
0
    int code = gdev_prn_get_params(dev, plist);
90
0
    int ecode = code;
91
0
    gs_param_string comprstr;
92
93
0
    if ((code = param_write_bool(plist, "BigEndian", &tfdev->BigEndian)) < 0)
94
0
        ecode = code;
95
0
#if (TIFFLIB_VERSION >= 20111221)
96
0
    if ((code = param_write_bool(plist, "UseBigTIFF", &tfdev->UseBigTIFF)) < 0)
97
0
        ecode = code;
98
0
#endif
99
0
    if ((code = param_write_bool(plist, "TIFFDateTime", &tfdev->write_datetime)) < 0)
100
0
        ecode = code;
101
0
    if ((code = tiff_compression_param_string(&comprstr, tfdev->Compression)) < 0 ||
102
0
        (code = param_write_string(plist, "Compression", &comprstr)) < 0)
103
0
        ecode = code;
104
0
    if ((code = param_write_long(plist, "MaxStripSize", &tfdev->MaxStripSize)) < 0)
105
0
        ecode = code;
106
0
    if ((code = param_write_long(plist, "AdjustWidth", &tfdev->AdjustWidth)) < 0)
107
0
        ecode = code;
108
0
    if (which & 1) {
109
0
        if ((code = gx_downscaler_write_params(plist, &tfdev->downscale,
110
0
                                               GX_DOWNSCALER_PARAMS_MFS |
111
0
                                               (which & 2 ? GX_DOWNSCALER_PARAMS_TRAP : 0) |
112
0
                                               (which & 4 ? GX_DOWNSCALER_PARAMS_ETS : 0))) < 0)
113
0
            ecode = code;
114
0
    }
115
0
    return ecode;
116
0
}
117
118
int
119
tiff_get_params(gx_device * dev, gs_param_list * plist)
120
0
{
121
0
    return tiff_get_some_params(dev, plist, 0);
122
0
}
123
124
int
125
tiff_get_params_downscale(gx_device * dev, gs_param_list * plist)
126
0
{
127
0
    return tiff_get_some_params(dev, plist, 1);
128
0
}
129
130
int
131
tiff_get_params_downscale_cmyk(gx_device * dev, gs_param_list * plist)
132
0
{
133
0
    return tiff_get_some_params(dev, plist, 3);
134
0
}
135
136
int
137
tiff_get_params_downscale_cmyk_ets(gx_device * dev, gs_param_list * plist)
138
0
{
139
0
    return tiff_get_some_params(dev, plist, 7);
140
0
}
141
142
static int
143
tiff_put_some_params(gx_device * dev, gs_param_list * plist, int which)
144
0
{
145
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)dev;
146
0
    int ecode = 0;
147
0
    int code;
148
0
    const char *param_name;
149
0
    bool big_endian = tfdev->BigEndian;
150
0
    bool usebigtiff = tfdev->UseBigTIFF;
151
0
    bool write_datetime = tfdev->write_datetime;
152
0
    uint16_t compr = tfdev->Compression;
153
0
    gs_param_string comprstr;
154
0
    long mss = tfdev->MaxStripSize;
155
0
    long aw = tfdev->AdjustWidth;
156
157
    /* Read BigEndian option as bool */
158
0
    switch (code = param_read_bool(plist, (param_name = "BigEndian"), &big_endian)) {
159
0
        default:
160
0
            ecode = code;
161
0
            param_signal_error(plist, param_name, ecode);
162
0
        case 0:
163
0
        case 1:
164
0
            break;
165
0
    }
166
167
    /* Read UseBigTIFF option as bool */
168
0
    switch (code = param_read_bool(plist, (param_name = "UseBigTIFF"), &usebigtiff)) {
169
0
        default:
170
0
            ecode = code;
171
0
            param_signal_error(plist, param_name, ecode);
172
0
        case 0:
173
0
        case 1:
174
0
            break;
175
0
    }
176
177
#if !(TIFFLIB_VERSION >= 20111221)
178
    if (usebigtiff)
179
        dmlprintf(dev->memory, "Warning: this version of libtiff does not support BigTIFF, ignoring parameter\n");
180
    usebigtiff = false;
181
#endif
182
183
0
    switch (code = param_read_bool(plist, (param_name = "TIFFDateTime"), &write_datetime)) {
184
0
        default:
185
0
            ecode = code;
186
0
            param_signal_error(plist, param_name, ecode);
187
0
        case 0:
188
0
        case 1:
189
0
            break;
190
0
    }
191
192
    /* Read Compression */
193
0
    switch (code = param_read_string(plist, (param_name = "Compression"), &comprstr)) {
194
0
        case 0:
195
0
            if ((ecode = tiff_compression_id(&compr, &comprstr)) < 0) {
196
197
0
                errprintf(tfdev->memory, "Unknown compression setting\n");
198
0
                param_signal_error(plist, param_name, ecode);
199
0
                return ecode;
200
0
            }
201
202
0
            if ( !tiff_compression_allowed(compr, (which & 1 ? 1 : (dev->color_info.depth / dev->color_info.num_components)))) {
203
204
0
                errprintf(tfdev->memory, "Invalid compression setting for this bitdepth\n");
205
0
                param_signal_error(plist, param_name, gs_error_rangecheck);
206
0
                return_error(gs_error_rangecheck);
207
0
            }
208
0
            break;
209
0
        case 1:
210
0
            break;
211
0
        default:
212
0
            ecode = code;
213
0
            param_signal_error(plist, param_name, ecode);
214
0
    }
215
0
    if (which & 1)
216
0
    {
217
0
        code = gx_downscaler_read_params(plist, &tfdev->downscale,
218
0
                                         (GX_DOWNSCALER_PARAMS_MFS |
219
0
                                          (which & 2 ? GX_DOWNSCALER_PARAMS_TRAP : 0) |
220
0
                                          (which & 4 ? GX_DOWNSCALER_PARAMS_ETS : 0)));
221
0
        if (code < 0)
222
0
        {
223
0
            ecode = code;
224
0
            param_signal_error(plist, param_name, ecode);
225
0
        }
226
0
    }
227
0
    switch (code = param_read_long(plist, (param_name = "MaxStripSize"), &mss)) {
228
0
        case 0:
229
            /*
230
             * Strip must be large enough to accommodate a raster line.
231
             * If the max strip size is too small, we still write a single
232
             * line per strip rather than giving an error.
233
             */
234
0
            if (mss >= 0)
235
0
                break;
236
0
            code = gs_error_rangecheck;
237
0
        default:
238
0
            ecode = code;
239
0
            param_signal_error(plist, param_name, ecode);
240
0
        case 1:
241
0
            break;
242
0
    }
243
0
    switch (code = param_read_long(plist, (param_name = "AdjustWidth"), &aw)) {
244
0
        case 0:
245
0
            if (aw >= 0)
246
0
                break;
247
0
            code = gs_error_rangecheck;
248
0
        default:
249
0
            ecode = code;
250
0
            param_signal_error(plist, param_name, ecode);
251
0
        case 1:
252
0
            break;
253
0
    }
254
255
0
    if (ecode < 0)
256
0
        return ecode;
257
0
    code = gdev_prn_put_params(dev, plist);
258
0
    if (code < 0)
259
0
        return code;
260
261
0
    tfdev->BigEndian = big_endian;
262
0
    tfdev->UseBigTIFF = usebigtiff;
263
0
    tfdev->write_datetime = write_datetime;
264
0
    tfdev->Compression = compr;
265
0
    tfdev->MaxStripSize = mss;
266
0
    tfdev->AdjustWidth = aw;
267
0
    return code;
268
0
}
269
270
int
271
tiff_put_params(gx_device * dev, gs_param_list * plist)
272
0
{
273
0
    return tiff_put_some_params(dev, plist, 0);
274
0
}
275
276
int
277
tiff_put_params_downscale(gx_device * dev, gs_param_list * plist)
278
0
{
279
0
    return tiff_put_some_params(dev, plist, 1);
280
0
}
281
282
int
283
tiff_put_params_downscale_cmyk(gx_device * dev, gs_param_list * plist)
284
0
{
285
0
    return tiff_put_some_params(dev, plist, 3);
286
0
}
287
288
int
289
tiff_put_params_downscale_cmyk_ets(gx_device * dev, gs_param_list * plist)
290
0
{
291
0
    return tiff_put_some_params(dev, plist, 7);
292
0
}
293
294
int gdev_tiff_begin_page(gx_device_tiff *tfdev,
295
                         gp_file *file)
296
0
{
297
0
    gx_device_printer *const pdev = (gx_device_printer *)tfdev;
298
0
    int code;
299
300
0
    if (gdev_prn_file_is_new(pdev)) {
301
        /* open the TIFF device */
302
0
        tfdev->tif = tiff_from_filep(pdev, pdev->dname, file, tfdev->BigEndian, tfdev->UseBigTIFF);
303
0
        if (!tfdev->tif)
304
0
            return_error(gs_error_invalidfileaccess);
305
        /* Set up the icc link settings at this time */
306
0
        code = gx_downscaler_create_post_render_link((gx_device *)pdev,
307
0
                                                     &tfdev->icclink);
308
0
        if (code < 0)
309
0
            return code;
310
0
    }
311
312
0
    return tiff_set_fields_for_printer(pdev, tfdev->tif, tfdev->downscale.downscale_factor,
313
0
                                       tfdev->AdjustWidth,
314
0
                                       tfdev->write_datetime);
315
0
}
316
317
int tiff_set_compression(gx_device_printer *pdev,
318
                         TIFF *tif,
319
                         uint compression,
320
                         long max_strip_size)
321
16.7k
{
322
16.7k
    TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
323
324
16.7k
    if (max_strip_size == 0) {
325
0
        TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, pdev->height);
326
0
    }
327
16.7k
    else {
328
16.7k
        int rows = 0;
329
330
16.7k
        if (pdev->width >=1) {
331
16.7k
            rows = max_strip_size /
332
16.7k
            gdev_mem_bytes_per_scan_line((gx_device *)pdev);
333
16.7k
            TIFFSetField(tif,
334
16.7k
                     TIFFTAG_ROWSPERSTRIP,
335
16.7k
                     TIFFDefaultStripSize(tif, max(1, rows)));
336
16.7k
        } else
337
12
            return_error(gs_error_rangecheck);
338
16.7k
    }
339
340
16.7k
    return 0;
341
16.7k
}
342
343
int tiff_set_fields_for_printer(gx_device_printer *pdev,
344
                                TIFF              *tif,
345
                                int                factor,
346
                                int                adjustWidth,
347
                                bool               writedatetime)
348
16.7k
{
349
16.7k
    int width = gx_downscaler_scale(pdev->width, factor);
350
16.7k
    int height = gx_downscaler_scale(pdev->height, factor);
351
16.7k
    int xpi = gx_downscaler_scale((int)pdev->x_pixels_per_inch, factor);
352
16.7k
    int ypi = gx_downscaler_scale((int)pdev->y_pixels_per_inch, factor);
353
16.7k
    width = fax_adjusted_width(width, adjustWidth);
354
16.7k
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
355
16.7k
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
356
16.7k
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
357
16.7k
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
358
359
16.7k
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
360
16.7k
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)xpi);
361
16.7k
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)ypi);
362
363
16.7k
#ifndef CLUSTER
364
16.7k
    {
365
16.7k
        char revs[32];
366
50.3k
#define maxSoftware 40
367
16.7k
        char softwareValue[maxSoftware];
368
16.7k
        int revision = gs_revision_number();
369
16.7k
        int major = (int)(revision / 1000);
370
16.7k
        int minor = (int)(revision - (major * 1000)) / 10;
371
16.7k
        int patch =  revision % 10;
372
373
16.7k
        strncpy(softwareValue, gs_product, maxSoftware);
374
16.7k
        softwareValue[maxSoftware - 1] = 0;
375
16.7k
        gs_snprintf(revs, sizeof(revs), " %d.%02d.%d", major, minor, patch);
376
16.7k
        strncat(softwareValue, revs,
377
16.7k
                maxSoftware - strlen(softwareValue) - 1);
378
379
16.7k
        TIFFSetField(tif, TIFFTAG_SOFTWARE, softwareValue);
380
16.7k
    }
381
16.7k
#endif
382
16.7k
    if (writedatetime) {
383
16.7k
        struct tm tms;
384
16.7k
        time_t t;
385
16.7k
        char dateTimeValue[20];
386
387
#ifdef CLUSTER
388
        memset(&t, 0, sizeof(t));
389
        memset(&tms, 0, sizeof(tms));
390
#else
391
16.7k
        time(&t);
392
16.7k
        tms = *localtime(&t);
393
16.7k
#endif
394
16.7k
        gs_snprintf(dateTimeValue, sizeof(dateTimeValue), "%04d:%02d:%02d %02d:%02d:%02d",
395
16.7k
                tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
396
16.7k
                tms.tm_hour, tms.tm_min, tms.tm_sec);
397
398
16.7k
        TIFFSetField(tif, TIFFTAG_DATETIME, dateTimeValue);
399
16.7k
    }
400
401
16.7k
    TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
402
16.7k
    TIFFSetField(tif, TIFFTAG_PAGENUMBER, pdev->PageCount, 0);
403
404
    /* Set the ICC profile.  Test to avoid issues with separations and also
405
       if the color space is set to LAB, we do that as an enumerated type. Do
406
       NOT set the profile if the bit depth is less than 8 or if fast color
407
       was used. */
408
16.7k
    if (pdev->color_info.depth >= 8) {
409
        /* Select from one of three profiles.. */
410
0
        cmm_profile_t *icc_profile;
411
412
0
        if (pdev->icc_struct->postren_profile != NULL)
413
0
            icc_profile = pdev->icc_struct->postren_profile;
414
0
        else
415
0
            icc_profile = pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
416
417
0
        if (icc_profile->num_comps == pdev->color_info.num_components &&
418
0
            icc_profile->data_cs != gsCIELAB && !(pdev->icc_struct->usefastcolor)) {
419
0
            TIFFSetField(tif, TIFFTAG_ICCPROFILE, icc_profile->buffer_size,
420
0
                icc_profile->buffer);
421
0
        }
422
0
    }
423
16.7k
    return 0;
424
16.7k
}
425
426
int
427
tiff_print_page(gx_device_printer *dev, TIFF *tif, int min_feature_size)
428
0
{
429
0
    int code = 0;
430
0
    byte *data;
431
0
    int size = gdev_mem_bytes_per_scan_line((gx_device *)dev);
432
0
    int max_size = max(size, TIFFScanlineSize(tif));
433
0
    int row;
434
0
    int bpc = dev->color_info.depth / dev->color_info.num_components;
435
0
    void *min_feature_data = NULL;
436
0
    int line_lag = 0;
437
0
    int filtered_count;
438
439
0
    data = gs_alloc_bytes(dev->memory, max_size, "tiff_print_page(data)");
440
0
    if (data == NULL)
441
0
        return_error(gs_error_VMerror);
442
0
    if (bpc != 1)
443
0
        min_feature_size = 1;
444
0
    if (min_feature_size > 1) {
445
0
        code = min_feature_size_init(dev->memory, min_feature_size,
446
0
                                     dev->width, dev->height,
447
0
                                     &min_feature_data);
448
0
        if (code < 0)
449
0
            goto cleanup;
450
0
    }
451
452
0
    code = TIFFCheckpointDirectory(tif);
453
454
0
    memset(data, 0, max_size);
455
0
    for (row = 0; row < dev->height && code >= 0; row++) {
456
0
        code = gdev_prn_copy_scan_lines(dev, row, data, size);
457
0
        if (code < 0)
458
0
            goto cleanup;
459
0
        if (min_feature_size > 1) {
460
0
            filtered_count = min_feature_size_process(data, min_feature_data);
461
0
            if (filtered_count == 0)
462
0
                line_lag++;
463
0
        }
464
465
0
        if (row - line_lag >= 0) {
466
0
#if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN)
467
0
            if (bpc == 16)
468
0
                TIFFSwabArrayOfShort((uint16_t *)data,
469
0
                                     dev->width * (long)dev->color_info.num_components);
470
0
#endif
471
472
0
            code = TIFFWriteScanline(tif, data, row - line_lag, 0);
473
0
        }
474
0
    }
475
0
    for (row -= line_lag ; row < dev->height && code >= 0; row++)
476
0
    {
477
0
        filtered_count = min_feature_size_process(data, min_feature_data);
478
0
        code = TIFFWriteScanline(tif, data, row, 0);
479
0
    }
480
481
0
    if (code >= 0)
482
0
        code = TIFFWriteDirectory(tif);
483
0
cleanup:
484
0
    if (min_feature_size > 1)
485
0
        min_feature_size_dnit(min_feature_data);
486
0
    gs_free_object(dev->memory, data, "tiff_print_page(data)");
487
488
0
    return code;
489
0
}
490
491
/* void gsicc_init_buffer(gsicc_bufferdesc_t *buffer_desc, unsigned char num_chan,
492
    unsigned char bytes_per_chan, bool has_alpha, bool alpha_first,
493
    bool is_planar, int plane_stride, int row_stride, int num_rows,
494
    int pixels_per_row); */
495
496
static int tiff_chunky_post_cm(void  *arg, byte **dst, byte **src, int w, int h,
497
    int raster)
498
0
{
499
0
    gsicc_bufferdesc_t input_buffer_desc, output_buffer_desc;
500
0
    gsicc_link_t *icclink = (gsicc_link_t*)arg;
501
502
0
    gsicc_init_buffer(&input_buffer_desc, icclink->num_input, 1, false,
503
0
        false, false, 0, raster, h, w);
504
0
    gsicc_init_buffer(&output_buffer_desc, icclink->num_output, 1, false,
505
0
        false, false, 0, raster, h, w);
506
0
    icclink->procs.map_buffer(NULL, icclink, &input_buffer_desc, &output_buffer_desc,
507
0
        src[0], dst[0]);
508
0
    return 0;
509
0
}
510
511
/* Special version, called with 8 bit grey input to be downsampled to 1bpp
512
 * output. */
513
int
514
tiff_downscale_and_print_page(gx_device_printer *dev, TIFF *tif,
515
                              gx_downscaler_params *params,
516
                              int aw, int bpc, int num_comps)
517
0
{
518
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)dev;
519
0
    int code = 0;
520
0
    byte *data = NULL;
521
0
    int size = gdev_mem_bytes_per_scan_line((gx_device *)dev);
522
0
    int max_size = max(size, TIFFScanlineSize(tif));
523
0
    int row;
524
0
    int factor = params->downscale_factor;
525
0
    int height = dev->height/factor;
526
0
    gx_downscaler_t ds;
527
528
0
    code = TIFFCheckpointDirectory(tif);
529
0
    if (code < 0)
530
0
        return code;
531
532
0
    if (tfdev->icclink == NULL) {
533
0
        code = gx_downscaler_init(&ds, (gx_device *)dev,
534
0
                                  8, bpc, num_comps,
535
0
                                  params,
536
0
                                  &fax_adjusted_width, aw);
537
0
    } else {
538
0
        code = gx_downscaler_init_cm(&ds, (gx_device *)dev,
539
0
                                     8, bpc, num_comps,
540
0
                                     params,
541
0
                                     &fax_adjusted_width, aw,
542
0
                                     tiff_chunky_post_cm, tfdev->icclink,
543
0
                                     tfdev->icclink->num_output);
544
0
    }
545
0
    if (code < 0)
546
0
        return code;
547
548
0
    data = gs_alloc_bytes(dev->memory, max_size, "tiff_print_page(data)");
549
0
    if (data == NULL) {
550
0
        gx_downscaler_fin(&ds);
551
0
        return_error(gs_error_VMerror);
552
0
    }
553
554
0
    for (row = 0; row < height && code >= 0; row++) {
555
0
        code = gx_downscaler_getbits(&ds, data, row);
556
0
        if (code < 0)
557
0
            break;
558
559
0
        code = TIFFWriteScanline(tif, data, row, 0);
560
0
        if (code < 0)
561
0
            break;
562
0
    }
563
564
0
    if (code >= 0)
565
0
        code = TIFFWriteDirectory(tif);
566
567
0
    gx_downscaler_fin(&ds);
568
0
    gs_free_object(dev->memory, data, "tiff_print_page(data)");
569
570
0
    return code;
571
0
}
572
573
574
static struct compression_string {
575
    uint16_t id;
576
    const char *str;
577
} compression_strings [] = {
578
    { COMPRESSION_NONE, "none" },
579
    { COMPRESSION_CCITTRLE, "crle" },
580
    { COMPRESSION_CCITTFAX3, "g3" },
581
    { COMPRESSION_CCITTFAX4, "g4" },
582
    { COMPRESSION_LZW, "lzw" },
583
    { COMPRESSION_PACKBITS, "pack" },
584
585
    { 0, NULL }
586
};
587
588
int
589
tiff_compression_param_string(gs_param_string *param, uint16_t id)
590
132k
{
591
132k
    struct compression_string *c;
592
529k
    for (c = compression_strings; c->str; c++)
593
529k
        if (id == c->id) {
594
132k
            param_string_from_string(*param, c->str);
595
132k
            return 0;
596
132k
        }
597
132k
    return_error(gs_error_undefined);
598
132k
}
599
600
int
601
tiff_compression_id(uint16_t *id, gs_param_string *param)
602
3.86k
{
603
3.86k
    struct compression_string *c;
604
15.4k
    for (c = compression_strings; c->str; c++)
605
15.4k
        if (!bytes_compare(param->data, param->size,
606
15.4k
                           (const byte *)c->str, strlen(c->str)))
607
3.86k
        {
608
3.86k
            *id = c->id;
609
3.86k
            return 0;
610
3.86k
        }
611
3.86k
    return_error(gs_error_undefined);
612
3.86k
}
613
614
int tiff_compression_allowed(uint16_t compression, byte depth)
615
3.86k
{
616
3.86k
    return ((depth == 1 && (compression == COMPRESSION_NONE ||
617
3.86k
                          compression == COMPRESSION_CCITTRLE ||
618
3.86k
                          compression == COMPRESSION_CCITTFAX3 ||
619
3.86k
                          compression == COMPRESSION_CCITTFAX4 ||
620
3.86k
                          compression == COMPRESSION_LZW ||
621
3.86k
                          compression == COMPRESSION_PACKBITS))
622
3.86k
           || ((depth == 8 || depth == 16) && (compression == COMPRESSION_NONE ||
623
0
                          compression == COMPRESSION_LZW ||
624
0
                          compression == COMPRESSION_PACKBITS)));
625
626
3.86k
}