Thu, 20 Mar 2003 06:54:08 +0000
more JPEG support. added input file handler API.
1 /*
2 * tumble: build a PDF file from image files
3 *
4 * $Id: tumble_tiff.c,v 1.1 2003/03/19 22:54:08 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 /* $$$ should we dup the file descriptor here, so that later closing f
69 won't cause problems? */
70 tiff_in = TIFFFdOpen (fileno (f), name, "r");
71 if (! tiff_in)
72 {
73 fprintf (stderr, "can't open input file '%s'\n", name);
74 return (0);
75 }
76 return (1);
77 }
80 bool last_tiff_input_page (void)
81 {
82 return (TIFFLastDirectory (tiff_in));
83 }
86 bool get_tiff_image_info (int image,
87 input_attributes_t input_attributes,
88 image_info_t *image_info)
89 {
90 uint32_t image_height, image_width;
91 uint16_t samples_per_pixel;
92 uint16_t bits_per_sample;
93 uint16_t planar_config;
95 uint16_t resolution_unit;
96 float x_resolution, y_resolution;
98 double dest_x_resolution, dest_y_resolution;
100 #ifdef CHECK_DEPTH
101 uint32_t image_depth;
102 #endif
104 if (! TIFFSetDirectory (tiff_in, image - 1))
105 {
106 fprintf (stderr, "can't find page %d of input file\n", image);
107 return (0);
108 }
109 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
110 {
111 fprintf (stderr, "can't get image height\n");
112 return (0);
113 }
114 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
115 {
116 fprintf (stderr, "can't get image width\n");
117 return (0);
118 }
120 if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
121 {
122 fprintf (stderr, "can't get samples per pixel\n");
123 return (0);
124 }
126 #ifdef CHECK_DEPTH
127 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
128 {
129 fprintf (stderr, "can't get image depth\n");
130 return (0);
131 }
132 #endif
134 if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
135 {
136 fprintf (stderr, "can't get bits per sample\n");
137 return (0);
138 }
140 if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
141 planar_config = 1;
143 if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
144 resolution_unit = 2;
145 if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
146 x_resolution = 300;
147 if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
148 y_resolution = 300;
150 if (samples_per_pixel != 1)
151 {
152 fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
153 return (0);
154 }
156 #ifdef CHECK_DEPTH
157 if (image_depth != 1)
158 {
159 fprintf (stderr, "image depth %u, must be 1\n", image_depth);
160 return (0);
161 }
162 #endif
164 if (bits_per_sample != 1)
165 {
166 fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
167 return (0);
168 }
170 if (planar_config != 1)
171 {
172 fprintf (stderr, "planar config %u, must be 1\n", planar_config);
173 return (0);
174 }
176 if (input_attributes.has_resolution)
177 {
178 x_resolution = input_attributes.x_resolution;
179 y_resolution = input_attributes.y_resolution;
180 }
182 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
183 {
184 image_info->width_samples = image_height;
185 image_info->height_samples = image_width;
186 dest_x_resolution = y_resolution;
187 dest_y_resolution = x_resolution;
188 SWAP (double, image_info->width_points, image_info->height_points);
189 }
190 else
191 {
192 image_info->width_samples = image_width;
193 image_info->height_samples = image_height;
194 dest_x_resolution = x_resolution;
195 dest_y_resolution = y_resolution;
196 }
198 image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
199 image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
201 if ((image_info->height_points > PAGE_MAX_POINTS) ||
202 (image_info->width_points > PAGE_MAX_POINTS))
203 {
204 fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
205 return (0);
206 }
208 return (1);
209 }
212 /* frees original! */
213 static Bitmap *resize_bitmap (Bitmap *src,
214 double x_resolution,
215 double y_resolution,
216 input_attributes_t input_attributes)
217 {
218 Rect src_rect;
219 Point dest_min;
220 Bitmap *dest;
222 int width_pixels = input_attributes.page_size.width * x_resolution;
223 int height_pixels = input_attributes.page_size.height * y_resolution;
225 src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
226 src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
227 src_rect.max.x = src_rect.min.x + width_pixels;
228 src_rect.max.y = src_rect.min.y + height_pixels;
230 dest_min.x = 0;
231 dest_min.y = 0;
233 dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
234 free_bitmap (src);
235 return (dest);
236 }
239 /* "in place" rotation */
240 static void rotate_bitmap (Bitmap *src,
241 input_attributes_t input_attributes)
242 {
243 switch (input_attributes.rotation)
244 {
245 case 0: break;
246 case 90: rot_90 (src); break;
247 case 180: rot_180 (src); break;
248 case 270: rot_270 (src); break;
249 default:
250 fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
251 }
252 }
255 bool process_tiff_image (int image, /* range 1 .. n */
256 input_attributes_t input_attributes,
257 image_info_t *image_info,
258 pdf_page_handle page)
259 {
260 Rect rect;
261 Bitmap *bitmap = NULL;
263 int row;
265 rect.min.x = 0;
266 rect.min.y = 0;
268 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
269 {
270 rect.max.x = image_info->height_samples;
271 rect.max.y = image_info->width_samples;
272 }
273 else
274 {
275 rect.max.x = image_info->width_samples;
276 rect.max.y = image_info->height_samples;
277 }
279 bitmap = create_bitmap (& rect);
281 if (! bitmap)
282 {
283 fprintf (stderr, "can't allocate bitmap\n");
284 fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
285 goto fail;
286 }
288 for (row = 0; row < rect.max.y; row++)
289 if (1 != TIFFReadScanline (tiff_in,
290 bitmap->bits + row * bitmap->row_words,
291 row,
292 0))
293 {
294 fprintf (stderr, "can't read TIFF scanline\n");
295 goto fail;
296 }
298 #ifdef TIFF_REVERSE_BITS
299 reverse_bits ((uint8_t *) bitmap->bits,
300 rect.max.y * bitmap->row_words * sizeof (word_t));
301 #endif /* TIFF_REVERSE_BITS */
303 #if 0
304 if (input_attributes.has_page_size)
305 bitmap = resize_bitmap (bitmap,
306 x_resolution,
307 y_resolution,
308 input_attributes);
309 #endif
311 rotate_bitmap (bitmap,
312 input_attributes);
314 #if 0
315 pdf_write_text (page);
316 #else
317 pdf_write_g4_fax_image (page,
318 0, 0, /* x, y */
319 image_info->width_points, image_info->height_points,
320 bitmap,
321 0, /* ImageMask */
322 0, 0, 0, /* r, g, b */
323 0); /* BlackIs1 */
324 #endif
326 if (bitmap)
327 free_bitmap (bitmap);
328 return (page);
330 fail:
331 if (bitmap)
332 free_bitmap (bitmap);
334 return (NULL);
335 }
338 input_handler_t tiff_handler =
339 {
340 open_tiff_input_file,
341 close_tiff_input_file,
342 last_tiff_input_page,
343 get_tiff_image_info,
344 process_tiff_image
345 };
348 void init_tiff_handler (void)
349 {
350 install_input_handler (& tiff_handler);
351 }