/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 | } |