tumble_tiff.c

Thu, 20 Mar 2003 07:06:35 +0000

author
eric
date
Thu, 20 Mar 2003 07:06:35 +0000
changeset 144
f2b7f70a965d
parent 142
cfa664f3129c
child 148
d4a6e303703a
permissions
-rw-r--r--

*** empty log message ***

eric@141 1 /*
eric@141 2 * tumble: build a PDF file from image files
eric@141 3 *
eric@142 4 * $Id: tumble_tiff.c,v 1.2 2003/03/19 23:02: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@141 28 #include <string.h>
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@141 47 bool close_tiff_input_file (void)
eric@141 48 {
eric@141 49 TIFFClose (tiff_in);
eric@141 50 return (1);
eric@141 51 }
eric@141 52
eric@141 53
eric@141 54 bool open_tiff_input_file (FILE *f, char *name)
eric@141 55 {
eric@141 56 uint8_t buf [2];
eric@141 57 size_t l;
eric@141 58
eric@141 59 l = fread (& buf [0], 1, sizeof (buf), f);
eric@141 60 if (l != sizeof (buf))
eric@141 61 return (0);
eric@141 62
eric@141 63 rewind (f);
eric@141 64
eric@141 65 if ((buf [0] != 0x49) || (buf [1] != 0x49))
eric@141 66 return (0);
eric@141 67
eric@141 68 tiff_in = TIFFFdOpen (fileno (f), name, "r");
eric@141 69 if (! tiff_in)
eric@141 70 {
eric@141 71 fprintf (stderr, "can't open input file '%s'\n", name);
eric@141 72 return (0);
eric@141 73 }
eric@141 74 return (1);
eric@141 75 }
eric@141 76
eric@141 77
eric@141 78 bool last_tiff_input_page (void)
eric@141 79 {
eric@141 80 return (TIFFLastDirectory (tiff_in));
eric@141 81 }
eric@141 82
eric@141 83
eric@141 84 bool get_tiff_image_info (int image,
eric@141 85 input_attributes_t input_attributes,
eric@141 86 image_info_t *image_info)
eric@141 87 {
eric@141 88 uint32_t image_height, image_width;
eric@141 89 uint16_t samples_per_pixel;
eric@141 90 uint16_t bits_per_sample;
eric@141 91 uint16_t planar_config;
eric@141 92
eric@141 93 uint16_t resolution_unit;
eric@141 94 float x_resolution, y_resolution;
eric@141 95
eric@141 96 double dest_x_resolution, dest_y_resolution;
eric@141 97
eric@141 98 #ifdef CHECK_DEPTH
eric@141 99 uint32_t image_depth;
eric@141 100 #endif
eric@141 101
eric@141 102 if (! TIFFSetDirectory (tiff_in, image - 1))
eric@141 103 {
eric@141 104 fprintf (stderr, "can't find page %d of input file\n", image);
eric@141 105 return (0);
eric@141 106 }
eric@141 107 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
eric@141 108 {
eric@141 109 fprintf (stderr, "can't get image height\n");
eric@141 110 return (0);
eric@141 111 }
eric@141 112 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
eric@141 113 {
eric@141 114 fprintf (stderr, "can't get image width\n");
eric@141 115 return (0);
eric@141 116 }
eric@141 117
eric@141 118 if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
eric@141 119 {
eric@141 120 fprintf (stderr, "can't get samples per pixel\n");
eric@141 121 return (0);
eric@141 122 }
eric@141 123
eric@141 124 #ifdef CHECK_DEPTH
eric@141 125 if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
eric@141 126 {
eric@141 127 fprintf (stderr, "can't get image depth\n");
eric@141 128 return (0);
eric@141 129 }
eric@141 130 #endif
eric@141 131
eric@141 132 if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
eric@141 133 {
eric@141 134 fprintf (stderr, "can't get bits per sample\n");
eric@141 135 return (0);
eric@141 136 }
eric@141 137
eric@141 138 if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
eric@141 139 planar_config = 1;
eric@141 140
eric@141 141 if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
eric@141 142 resolution_unit = 2;
eric@141 143 if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
eric@141 144 x_resolution = 300;
eric@141 145 if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
eric@141 146 y_resolution = 300;
eric@141 147
eric@141 148 if (samples_per_pixel != 1)
eric@141 149 {
eric@141 150 fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
eric@141 151 return (0);
eric@141 152 }
eric@141 153
eric@141 154 #ifdef CHECK_DEPTH
eric@141 155 if (image_depth != 1)
eric@141 156 {
eric@141 157 fprintf (stderr, "image depth %u, must be 1\n", image_depth);
eric@141 158 return (0);
eric@141 159 }
eric@141 160 #endif
eric@141 161
eric@141 162 if (bits_per_sample != 1)
eric@141 163 {
eric@141 164 fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
eric@141 165 return (0);
eric@141 166 }
eric@141 167
eric@141 168 if (planar_config != 1)
eric@141 169 {
eric@141 170 fprintf (stderr, "planar config %u, must be 1\n", planar_config);
eric@141 171 return (0);
eric@141 172 }
eric@141 173
eric@141 174 if (input_attributes.has_resolution)
eric@141 175 {
eric@141 176 x_resolution = input_attributes.x_resolution;
eric@141 177 y_resolution = input_attributes.y_resolution;
eric@141 178 }
eric@141 179
eric@141 180 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
eric@141 181 {
eric@141 182 image_info->width_samples = image_height;
eric@141 183 image_info->height_samples = image_width;
eric@141 184 dest_x_resolution = y_resolution;
eric@141 185 dest_y_resolution = x_resolution;
eric@141 186 SWAP (double, image_info->width_points, image_info->height_points);
eric@141 187 }
eric@141 188 else
eric@141 189 {
eric@141 190 image_info->width_samples = image_width;
eric@141 191 image_info->height_samples = image_height;
eric@141 192 dest_x_resolution = x_resolution;
eric@141 193 dest_y_resolution = y_resolution;
eric@141 194 }
eric@141 195
eric@141 196 image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
eric@141 197 image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
eric@141 198
eric@141 199 if ((image_info->height_points > PAGE_MAX_POINTS) ||
eric@141 200 (image_info->width_points > PAGE_MAX_POINTS))
eric@141 201 {
eric@141 202 fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
eric@141 203 return (0);
eric@141 204 }
eric@141 205
eric@141 206 return (1);
eric@141 207 }
eric@141 208
eric@141 209
eric@141 210 /* frees original! */
eric@141 211 static Bitmap *resize_bitmap (Bitmap *src,
eric@141 212 double x_resolution,
eric@141 213 double y_resolution,
eric@141 214 input_attributes_t input_attributes)
eric@141 215 {
eric@141 216 Rect src_rect;
eric@141 217 Point dest_min;
eric@141 218 Bitmap *dest;
eric@141 219
eric@141 220 int width_pixels = input_attributes.page_size.width * x_resolution;
eric@141 221 int height_pixels = input_attributes.page_size.height * y_resolution;
eric@141 222
eric@141 223 src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
eric@141 224 src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
eric@141 225 src_rect.max.x = src_rect.min.x + width_pixels;
eric@141 226 src_rect.max.y = src_rect.min.y + height_pixels;
eric@141 227
eric@141 228 dest_min.x = 0;
eric@141 229 dest_min.y = 0;
eric@141 230
eric@141 231 dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
eric@141 232 free_bitmap (src);
eric@141 233 return (dest);
eric@141 234 }
eric@141 235
eric@141 236
eric@141 237 /* "in place" rotation */
eric@141 238 static void rotate_bitmap (Bitmap *src,
eric@141 239 input_attributes_t input_attributes)
eric@141 240 {
eric@141 241 switch (input_attributes.rotation)
eric@141 242 {
eric@141 243 case 0: break;
eric@141 244 case 90: rot_90 (src); break;
eric@141 245 case 180: rot_180 (src); break;
eric@141 246 case 270: rot_270 (src); break;
eric@141 247 default:
eric@141 248 fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
eric@141 249 }
eric@141 250 }
eric@141 251
eric@141 252
eric@141 253 bool process_tiff_image (int image, /* range 1 .. n */
eric@141 254 input_attributes_t input_attributes,
eric@141 255 image_info_t *image_info,
eric@141 256 pdf_page_handle page)
eric@141 257 {
eric@141 258 Rect rect;
eric@141 259 Bitmap *bitmap = NULL;
eric@141 260
eric@141 261 int row;
eric@141 262
eric@141 263 rect.min.x = 0;
eric@141 264 rect.min.y = 0;
eric@141 265
eric@141 266 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
eric@141 267 {
eric@141 268 rect.max.x = image_info->height_samples;
eric@141 269 rect.max.y = image_info->width_samples;
eric@141 270 }
eric@141 271 else
eric@141 272 {
eric@141 273 rect.max.x = image_info->width_samples;
eric@141 274 rect.max.y = image_info->height_samples;
eric@141 275 }
eric@141 276
eric@141 277 bitmap = create_bitmap (& rect);
eric@141 278
eric@141 279 if (! bitmap)
eric@141 280 {
eric@141 281 fprintf (stderr, "can't allocate bitmap\n");
eric@141 282 fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
eric@141 283 goto fail;
eric@141 284 }
eric@141 285
eric@141 286 for (row = 0; row < rect.max.y; row++)
eric@141 287 if (1 != TIFFReadScanline (tiff_in,
eric@141 288 bitmap->bits + row * bitmap->row_words,
eric@141 289 row,
eric@141 290 0))
eric@141 291 {
eric@141 292 fprintf (stderr, "can't read TIFF scanline\n");
eric@141 293 goto fail;
eric@141 294 }
eric@141 295
eric@141 296 #ifdef TIFF_REVERSE_BITS
eric@141 297 reverse_bits ((uint8_t *) bitmap->bits,
eric@141 298 rect.max.y * bitmap->row_words * sizeof (word_t));
eric@141 299 #endif /* TIFF_REVERSE_BITS */
eric@141 300
eric@141 301 #if 0
eric@141 302 if (input_attributes.has_page_size)
eric@141 303 bitmap = resize_bitmap (bitmap,
eric@141 304 x_resolution,
eric@141 305 y_resolution,
eric@141 306 input_attributes);
eric@141 307 #endif
eric@141 308
eric@141 309 rotate_bitmap (bitmap,
eric@141 310 input_attributes);
eric@141 311
eric@141 312 #if 0
eric@141 313 pdf_write_text (page);
eric@141 314 #else
eric@141 315 pdf_write_g4_fax_image (page,
eric@141 316 0, 0, /* x, y */
eric@141 317 image_info->width_points, image_info->height_points,
eric@141 318 bitmap,
eric@141 319 0, /* ImageMask */
eric@141 320 0, 0, 0, /* r, g, b */
eric@141 321 0); /* BlackIs1 */
eric@141 322 #endif
eric@141 323
eric@141 324 if (bitmap)
eric@141 325 free_bitmap (bitmap);
eric@141 326 return (page);
eric@141 327
eric@141 328 fail:
eric@141 329 if (bitmap)
eric@141 330 free_bitmap (bitmap);
eric@141 331
eric@141 332 return (NULL);
eric@141 333 }
eric@141 334
eric@141 335
eric@141 336 input_handler_t tiff_handler =
eric@141 337 {
eric@141 338 open_tiff_input_file,
eric@141 339 close_tiff_input_file,
eric@141 340 last_tiff_input_page,
eric@141 341 get_tiff_image_info,
eric@141 342 process_tiff_image
eric@141 343 };
eric@141 344
eric@141 345
eric@141 346 void init_tiff_handler (void)
eric@141 347 {
eric@141 348 install_input_handler (& tiff_handler);
eric@141 349 }