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