1 /* Copyright (C) 2001-2019 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
tiff_set_rgb_fields(gx_device_tiff * tfdev)102 tiff_set_rgb_fields(gx_device_tiff *tfdev)
103 {
104     /* Put in a switch statement in case we want to have others */
105     switch (tfdev->icc_struct->device_profile[0]->data_cs) {
106         case gsRGB:
107             TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
108             break;
109         case gsCIELAB:
110             TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB);
111             break;
112         default:
113             TIFFSetField(tfdev->tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
114             break;
115     }
116     TIFFSetField(tfdev->tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
117     TIFFSetField(tfdev->tif, TIFFTAG_SAMPLESPERPIXEL, 3);
118 
119     tiff_set_compression((gx_device_printer *)tfdev, tfdev->tif,
120                          tfdev->Compression, tfdev->MaxStripSize);
121 }
122 
123 static int
tiff12_print_page(gx_device_printer * pdev,gp_file * file)124 tiff12_print_page(gx_device_printer * pdev, gp_file * file)
125 {
126     gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
127     int code;
128 
129     code = gdev_tiff_begin_page(tfdev, file);
130     if (code < 0)
131         return code;
132 
133     TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE, 4);
134     tiff_set_rgb_fields(tfdev);
135 
136     TIFFCheckpointDirectory(tfdev->tif);
137 
138     /* Write the page data. */
139     {
140         int y;
141         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         int size_alloc = size + 5;
146         byte *data = gs_alloc_bytes(pdev->memory, size_alloc, "tiff12_print_page");
147 
148         if (data == 0)
149             return_error(gs_error_VMerror);
150 
151         memset(data, 0, size_alloc);
152 
153         for (y = 0; y < pdev->height; ++y) {
154             const byte *src;
155             byte *dest;
156             int x;
157 
158             code = gdev_prn_copy_scan_lines(pdev, y, data, size);
159             if (code < 0)
160                 break;
161 
162             for (src = data, dest = data, x = 0; x < size;
163                  src += 6, dest += 3, x += 6
164                 ) {
165                 dest[0] = (src[0] & 0xf0) | (src[1] >> 4);
166                 dest[1] = (src[2] & 0xf0) | (src[3] >> 4);
167                 dest[2] = (src[4] & 0xf0) | (src[5] >> 4);
168             }
169             TIFFWriteScanline(tfdev->tif, data, y, 0);
170         }
171         gs_free_object(pdev->memory, data, "tiff12_print_page");
172 
173         TIFFWriteDirectory(tfdev->tif);
174     }
175 
176     return code;
177 }
178 
179 static int
tiff_rgb_print_page(gx_device_printer * pdev,gp_file * file)180 tiff_rgb_print_page(gx_device_printer * pdev, gp_file * file)
181 {
182     gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
183     int code;
184 
185     code = gdev_tiff_begin_page(tfdev, file);
186     if (code < 0)
187         return code;
188 
189     TIFFSetField(tfdev->tif, TIFFTAG_BITSPERSAMPLE,
190                  pdev->color_info.depth / pdev->color_info.num_components);
191     tiff_set_rgb_fields(tfdev);
192 
193     /* Write the page data. */
194     return tiff_print_page(pdev, tfdev->tif, 0);
195 }
196