Thu, 20 Mar 2003 07:03:29 +0000
no DEBUG in release version.
1 /*
2 * tumble: build a PDF file from image files
3 *
4 * $Id: tumble_tiff.c,v 1.2 2003/03/19 23:02:28 eric Exp $
5 * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. Note that permission is
10 * not granted to redistribute this program under the terms of any
11 * other version of the General Public License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
21 */
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include <tiffio.h>
31 #define TIFF_REVERSE_BITS
34 #include "semantics.h"
35 #include "tumble.h"
36 #include "bitblt.h"
37 #include "pdf.h"
38 #include "tumble_input.h"
41 TIFF *tiff_in;
44 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
47 bool close_tiff_input_file (void)
48 {
49 TIFFClose (tiff_in);
50 return (1);
51 }
54 bool open_tiff_input_file (FILE *f, char *name)
55 {
56 uint8_t buf [2];
57 size_t l;
59 l = fread (& buf [0], 1, sizeof (buf), f);
60 if (l != sizeof (buf))
61 return (0);
63 rewind (f);
65 if ((buf [0] != 0x49) || (buf [1] != 0x49))
66 return (0);
68 tiff_in = TIFFFdOpen (fileno (f), name, "r");
69 if (! tiff_in)
70 {
71 fprintf (stderr, "can't open input file '%s'\n", name);
72 return (0);
73 }
74 return (1);
75 }
78 bool last_tiff_input_page (void)
79 {
80 return (TIFFLastDirectory (tiff_in));
81 }
84 bool get_tiff_image_info (int image,
85 input_attributes_t input_attributes,
86 image_info_t *image_info)
87 {
88 uint32_t image_height, image_width;
89 uint16_t samples_per_pixel;
90 uint16_t bits_per_sample;
91 uint16_t planar_config;
93 uint16_t resolution_unit;
94 float x_resolution, y_resolution;
96 double dest_x_resolution, dest_y_resolution;
98 #ifdef CHECK_DEPTH
99 uint32_t image_depth;
100 #endif
102 if (! TIFFSetDirectory (tiff_in, image - 1))
103 {
104 fprintf (stderr, "can't find page %d of input file\n", image);
105 return (0);
106 }
107 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
108 {
109 fprintf (stderr, "can't get image height\n");
110 return (0);
111 }
112 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
113 {
114 fprintf (stderr, "can't get image width\n");
115 return (0);
116 }
118 if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
119 {
120 fprintf (stderr, "can't get samples per pixel\n");
121 return (0);
122 }
124 #ifdef CHECK_DEPTH
125 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
126 {
127 fprintf (stderr, "can't get image depth\n");
128 return (0);
129 }
130 #endif
132 if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
133 {
134 fprintf (stderr, "can't get bits per sample\n");
135 return (0);
136 }
138 if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
139 planar_config = 1;
141 if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
142 resolution_unit = 2;
143 if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
144 x_resolution = 300;
145 if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
146 y_resolution = 300;
148 if (samples_per_pixel != 1)
149 {
150 fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
151 return (0);
152 }
154 #ifdef CHECK_DEPTH
155 if (image_depth != 1)
156 {
157 fprintf (stderr, "image depth %u, must be 1\n", image_depth);
158 return (0);
159 }
160 #endif
162 if (bits_per_sample != 1)
163 {
164 fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
165 return (0);
166 }
168 if (planar_config != 1)
169 {
170 fprintf (stderr, "planar config %u, must be 1\n", planar_config);
171 return (0);
172 }
174 if (input_attributes.has_resolution)
175 {
176 x_resolution = input_attributes.x_resolution;
177 y_resolution = input_attributes.y_resolution;
178 }
180 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
181 {
182 image_info->width_samples = image_height;
183 image_info->height_samples = image_width;
184 dest_x_resolution = y_resolution;
185 dest_y_resolution = x_resolution;
186 SWAP (double, image_info->width_points, image_info->height_points);
187 }
188 else
189 {
190 image_info->width_samples = image_width;
191 image_info->height_samples = image_height;
192 dest_x_resolution = x_resolution;
193 dest_y_resolution = y_resolution;
194 }
196 image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
197 image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
199 if ((image_info->height_points > PAGE_MAX_POINTS) ||
200 (image_info->width_points > PAGE_MAX_POINTS))
201 {
202 fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
203 return (0);
204 }
206 return (1);
207 }
210 /* frees original! */
211 static Bitmap *resize_bitmap (Bitmap *src,
212 double x_resolution,
213 double y_resolution,
214 input_attributes_t input_attributes)
215 {
216 Rect src_rect;
217 Point dest_min;
218 Bitmap *dest;
220 int width_pixels = input_attributes.page_size.width * x_resolution;
221 int height_pixels = input_attributes.page_size.height * y_resolution;
223 src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
224 src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
225 src_rect.max.x = src_rect.min.x + width_pixels;
226 src_rect.max.y = src_rect.min.y + height_pixels;
228 dest_min.x = 0;
229 dest_min.y = 0;
231 dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
232 free_bitmap (src);
233 return (dest);
234 }
237 /* "in place" rotation */
238 static void rotate_bitmap (Bitmap *src,
239 input_attributes_t input_attributes)
240 {
241 switch (input_attributes.rotation)
242 {
243 case 0: break;
244 case 90: rot_90 (src); break;
245 case 180: rot_180 (src); break;
246 case 270: rot_270 (src); break;
247 default:
248 fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
249 }
250 }
253 bool process_tiff_image (int image, /* range 1 .. n */
254 input_attributes_t input_attributes,
255 image_info_t *image_info,
256 pdf_page_handle page)
257 {
258 Rect rect;
259 Bitmap *bitmap = NULL;
261 int row;
263 rect.min.x = 0;
264 rect.min.y = 0;
266 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
267 {
268 rect.max.x = image_info->height_samples;
269 rect.max.y = image_info->width_samples;
270 }
271 else
272 {
273 rect.max.x = image_info->width_samples;
274 rect.max.y = image_info->height_samples;
275 }
277 bitmap = create_bitmap (& rect);
279 if (! bitmap)
280 {
281 fprintf (stderr, "can't allocate bitmap\n");
282 fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
283 goto fail;
284 }
286 for (row = 0; row < rect.max.y; row++)
287 if (1 != TIFFReadScanline (tiff_in,
288 bitmap->bits + row * bitmap->row_words,
289 row,
290 0))
291 {
292 fprintf (stderr, "can't read TIFF scanline\n");
293 goto fail;
294 }
296 #ifdef TIFF_REVERSE_BITS
297 reverse_bits ((uint8_t *) bitmap->bits,
298 rect.max.y * bitmap->row_words * sizeof (word_t));
299 #endif /* TIFF_REVERSE_BITS */
301 #if 0
302 if (input_attributes.has_page_size)
303 bitmap = resize_bitmap (bitmap,
304 x_resolution,
305 y_resolution,
306 input_attributes);
307 #endif
309 rotate_bitmap (bitmap,
310 input_attributes);
312 #if 0
313 pdf_write_text (page);
314 #else
315 pdf_write_g4_fax_image (page,
316 0, 0, /* x, y */
317 image_info->width_points, image_info->height_points,
318 bitmap,
319 0, /* ImageMask */
320 0, 0, 0, /* r, g, b */
321 0); /* BlackIs1 */
322 #endif
324 if (bitmap)
325 free_bitmap (bitmap);
326 return (page);
328 fail:
329 if (bitmap)
330 free_bitmap (bitmap);
332 return (NULL);
333 }
336 input_handler_t tiff_handler =
337 {
338 open_tiff_input_file,
339 close_tiff_input_file,
340 last_tiff_input_page,
341 get_tiff_image_info,
342 process_tiff_image
343 };
346 void init_tiff_handler (void)
347 {
348 install_input_handler (& tiff_handler);
349 }