tumble_tiff.c

Thu, 20 Mar 2003 14:55:28 +0000

author
eric
date
Thu, 20 Mar 2003 14:55:28 +0000
changeset 151
83a99cc69861
parent 148
d4a6e303703a
child 152
e69798068425
permissions
-rw-r--r--

added match_suffix() to input handlers.

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