xref: /plan9/sys/src/cmd/gs/src/gdevtfnx.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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