tumble_tiff.c

Thu, 20 Mar 2003 06:54:08 +0000

author
eric
date
Thu, 20 Mar 2003 06:54:08 +0000
changeset 141
752599b50ff3
child 142
cfa664f3129c
permissions
-rw-r--r--

more JPEG support. added input file handler API.

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