1 /* Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevtfnx.c,v 1.7 2002/02/21 22:24:52 giles Exp $ */
18 /* 12-bit & 24-bit RGB uncompressed TIFF driver */
19 #include "gdevprn.h"
20 #include "gdevtifs.h"
21
22 /*
23 * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original
24 * version of this code to Ghostscript.
25 */
26
27 /* ------ The device descriptors ------ */
28
29 /* Default X and Y resolution */
30 #define X_DPI 72
31 #define Y_DPI 72
32
33 typedef struct gx_device_tiff_s {
34 gx_device_common;
35 gx_prn_device_common;
36 gdev_tiff_state tiff;
37 } gx_device_tiff;
38
39 private dev_proc_print_page(tiff12_print_page);
40 private dev_proc_print_page(tiff24_print_page);
41
42 private const gx_device_procs tiff12_procs =
43 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
44 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
45 private const gx_device_procs tiff24_procs =
46 prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
47 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
48
49 const gx_device_printer gs_tiff12nc_device = {
50 prn_device_std_body(gx_device_tiff, tiff12_procs, "tiff12nc",
51 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
52 X_DPI, Y_DPI,
53 0, 0, 0, 0,
54 24, tiff12_print_page)
55 };
56
57 const gx_device_printer gs_tiff24nc_device = {
58 prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff24nc",
59 DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
60 X_DPI, Y_DPI,
61 0, 0, 0, 0,
62 24, tiff24_print_page)
63 };
64
65 /* ------ Private definitions ------ */
66
67 /* Define our TIFF directory - sorted by tag number */
68 typedef struct tiff_rgb_directory_s {
69 TIFF_dir_entry BitsPerSample;
70 TIFF_dir_entry Compression;
71 TIFF_dir_entry Photometric;
72 TIFF_dir_entry FillOrder;
73 TIFF_dir_entry SamplesPerPixel;
74 } tiff_rgb_directory;
75 typedef struct tiff_rgb_values_s {
76 TIFF_ushort bps[3];
77 } tiff_rgb_values;
78
79 private const tiff_rgb_directory dir_rgb_template =
80 {
81 /* C's ridiculous rules about & and arrays require bps[0] here: */
82 {TIFFTAG_BitsPerSample, TIFF_SHORT | TIFF_INDIRECT, 3, offset_of(tiff_rgb_values, bps[0])},
83 {TIFFTAG_Compression, TIFF_SHORT, 1, Compression_none},
84 {TIFFTAG_Photometric, TIFF_SHORT, 1, Photometric_RGB},
85 {TIFFTAG_FillOrder, TIFF_SHORT, 1, FillOrder_MSB2LSB},
86 {TIFFTAG_SamplesPerPixel, TIFF_SHORT, 1, 3},
87 };
88
89 private const tiff_rgb_values val_12_template = {
90 {4, 4, 4}
91 };
92
93 private const tiff_rgb_values val_24_template = {
94 {8, 8, 8}
95 };
96
97 /* ------ Private functions ------ */
98
99 private int
tiff12_print_page(gx_device_printer * pdev,FILE * file)100 tiff12_print_page(gx_device_printer * pdev, FILE * file)
101 {
102 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
103 int code;
104
105 /* Write the page directory. */
106 code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
107 (const TIFF_dir_entry *)&dir_rgb_template,
108 sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
109 (const byte *)&val_12_template,
110 sizeof(val_12_template), 0);
111 if (code < 0)
112 return code;
113
114 /* Write the page data. */
115 {
116 int y;
117 int raster = gdev_prn_raster(pdev);
118 byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff12_print_page");
119 byte *row;
120
121 if (line == 0)
122 return_error(gs_error_VMerror);
123
124 for (y = 0; y < pdev->height; ++y) {
125 const byte *src;
126 byte *dest;
127 int x;
128
129 code = gdev_prn_get_bits(pdev, y, line, &row);
130 if (code < 0)
131 break;
132
133 for (src = row, dest = line, x = 0; x < raster;
134 src += 6, dest += 3, x += 6
135 ) {
136 dest[0] = (src[0] & 0xf0) | (src[1] >> 4);
137 dest[1] = (src[2] & 0xf0) | (src[3] >> 4);
138 dest[2] = (src[4] & 0xf0) | (src[5] >> 4);
139 }
140 fwrite(line, 1, (pdev->width * 3 + 1) >> 1, file);
141 }
142
143 gdev_tiff_end_strip(&tfdev->tiff, file);
144 gdev_tiff_end_page(&tfdev->tiff, file);
145 gs_free_object(pdev->memory, line, "tiff12_print_page");
146 }
147
148 return code;
149 }
150
151 private int
tiff24_print_page(gx_device_printer * pdev,FILE * file)152 tiff24_print_page(gx_device_printer * pdev, FILE * file)
153 {
154 gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
155 int code;
156
157 /* Write the page directory. */
158 code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
159 (const TIFF_dir_entry *)&dir_rgb_template,
160 sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
161 (const byte *)&val_24_template,
162 sizeof(val_24_template), 0);
163 if (code < 0)
164 return code;
165
166 /* Write the page data. */
167 {
168 int y;
169 int raster = gdev_prn_raster(pdev);
170 byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff24_print_page");
171 byte *row;
172
173 if (line == 0)
174 return_error(gs_error_VMerror);
175 for (y = 0; y < pdev->height; ++y) {
176 code = gdev_prn_get_bits(pdev, y, line, &row);
177 if (code < 0)
178 break;
179 fwrite((char *)row, raster, 1, file);
180 }
181 gdev_tiff_end_strip(&tfdev->tiff, file);
182 gdev_tiff_end_page(&tfdev->tiff, file);
183 gs_free_object(pdev->memory, line, "tiff24_print_page");
184 }
185
186 return code;
187 }
188