Coverage Report

Created: 2025-04-22 06:20

/src/libspectre/ghostscript/devices/gdevtfnx.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
/* 12-bit & 24-bit RGB uncompressed TIFF driver */
18
19
#include "stdint_.h"   /* for tiff.h */
20
#include "gdevtifs.h"
21
#include "gdevprn.h"
22
#include "gscms.h"
23
24
#include "gstiffio.h"
25
26
/*
27
 * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original
28
 * version of this code to Ghostscript.
29
 */
30
31
/* ------ The device descriptors ------ */
32
33
/* Default X and Y resolution */
34
#define X_DPI 72
35
#define Y_DPI 72
36
37
static dev_proc_print_page(tiff12_print_page);
38
static dev_proc_print_page(tiff_rgb_print_page);
39
40
/* FIXME: From initial analysis this is NOT safe for bg_printing, but might be fixable */
41
42
static const gx_device_procs tiff12_procs =
43
prn_color_params_procs(tiff_open, gdev_prn_output_page_seekable, tiff_close,
44
                gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
45
                tiff_get_params, tiff_put_params);
46
static const gx_device_procs tiff24_procs =
47
prn_color_params_procs(tiff_open, gdev_prn_output_page_seekable, tiff_close,
48
                gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
49
                tiff_get_params, tiff_put_params);
50
51
const gx_device_tiff gs_tiff12nc_device = {
52
    prn_device_std_body(gx_device_tiff, tiff12_procs, "tiff12nc",
53
                        DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
54
                        X_DPI, Y_DPI,
55
                        0, 0, 0, 0,
56
                        24, tiff12_print_page),
57
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
58
    false,                      /* default to not bigtiff */
59
    COMPRESSION_NONE,
60
    TIFF_DEFAULT_STRIP_SIZE,
61
    0, /* Adjust size */
62
    true, /* write_datetime */
63
    GX_DOWNSCALER_PARAMS_DEFAULTS,
64
    0 /* icclink */
65
};
66
67
const gx_device_tiff gs_tiff24nc_device = {
68
    prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff24nc",
69
                        DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
70
                        X_DPI, Y_DPI,
71
                        0, 0, 0, 0,
72
                        24, tiff_rgb_print_page),
73
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
74
    false,                      /* default to not bigtiff */
75
    COMPRESSION_NONE,
76
    TIFF_DEFAULT_STRIP_SIZE,
77
    0, /* Adjust size */
78
    true, /* write_datetime */
79
    GX_DOWNSCALER_PARAMS_DEFAULTS,
80
    0 /* icclink */
81
};
82
83
const gx_device_tiff gs_tiff48nc_device = {
84
    prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff48nc",
85
                        DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
86
                        X_DPI, Y_DPI,
87
                        0, 0, 0, 0,
88
                        48, tiff_rgb_print_page),
89
    ARCH_IS_BIG_ENDIAN          /* default to native endian (i.e. use big endian iff the platform is so*/,
90
    false,                      /* default to not bigtiff */
91
    COMPRESSION_NONE,
92
    TIFF_DEFAULT_STRIP_SIZE,
93
    0, /* Adjust size */
94
    true, /* write_datetime */
95
    GX_DOWNSCALER_PARAMS_DEFAULTS,
96
    0 /* icclink */
97
};
98
99
/* ------ Private functions ------ */
100
101
static void
102
tiff_set_rgb_fields(gx_device_tiff *tfdev)
103
0
{
104
    /* Put in a switch statement in case we want to have others */
105
0
    switch (tfdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->data_cs) {
106
0
        case gsRGB:
107
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
108
0
            break;
109
0
        case gsCIELAB:
110
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB);
111
0
            break;
112
0
        default:
113
0
            TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
114
0
            break;
115
0
    }
116
0
    TIFFSetField(tfdev->tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
117
0
    TIFFSetField(tfdev->tif, TIFFTAG_SAMPLESPERPIXEL, 3);
118
119
0
    tiff_set_compression((gx_device_printer *)tfdev, tfdev->tif,
120
0
                         tfdev->Compression, tfdev->MaxStripSize);
121
0
}
122
123
static int
124
tiff12_print_page(gx_device_printer * pdev, gp_file * file)
125
0
{
126
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
127
0
    int code;
128
129
0
    code = gdev_tiff_begin_page(tfdev, file);
130
0
    if (code < 0)
131
0
        return code;
132
133
0
    TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE, 4);
134
0
    tiff_set_rgb_fields(tfdev);
135
136
0
    TIFFCheckpointDirectory(tfdev->tif);
137
138
    /* Write the page data. */
139
0
    {
140
0
        int y;
141
0
        int size = gdev_prn_raster(pdev);
142
143
        /* We allocate an extra 5 bytes to avoid buffer overflow when accessing
144
        src[5] below, if size if not multiple of 6. This fixes bug-701807. */
145
0
        int size_alloc = size + 5;
146
0
        byte *data = gs_alloc_bytes(pdev->memory, size_alloc, "tiff12_print_page");
147
148
0
        if (data == 0)
149
0
            return_error(gs_error_VMerror);
150
151
0
        memset(data, 0, size_alloc);
152
153
0
        for (y = 0; y < pdev->height; ++y) {
154
0
            const byte *src;
155
0
            byte *dest;
156
0
            int x;
157
158
0
            code = gdev_prn_copy_scan_lines(pdev, y, data, size);
159
0
            if (code < 0)
160
0
                break;
161
162
0
            for (src = data, dest = data, x = 0; x < size;
163
0
                 src += 6, dest += 3, x += 6
164
0
                ) {
165
0
                dest[0] = (src[0] & 0xf0) | (src[1] >> 4);
166
0
                dest[1] = (src[2] & 0xf0) | (src[3] >> 4);
167
0
                dest[2] = (src[4] & 0xf0) | (src[5] >> 4);
168
0
            }
169
0
            TIFFWriteScanline(tfdev->tif, data, y, 0);
170
0
        }
171
0
        gs_free_object(pdev->memory, data, "tiff12_print_page");
172
173
0
        TIFFWriteDirectory(tfdev->tif);
174
0
    }
175
176
0
    return code;
177
0
}
178
179
static int
180
tiff_rgb_print_page(gx_device_printer * pdev, gp_file * file)
181
0
{
182
0
    gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
183
0
    int code;
184
185
0
    code = gdev_tiff_begin_page(tfdev, file);
186
0
    if (code < 0)
187
0
        return code;
188
189
0
    TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE,
190
0
                 pdev->color_info.depth / pdev->color_info.num_components);
191
0
    tiff_set_rgb_fields(tfdev);
192
193
    /* Write the page data. */
194
0
    return tiff_print_page(pdev, tfdev->tif, 0);
195
0
}