1.1 --- a/tumble.c Thu Mar 20 01:08:05 2003 +0000 1.2 +++ b/tumble.c Thu Mar 20 06:54:08 2003 +0000 1.3 @@ -2,7 +2,7 @@ 1.4 * tumble: build a PDF file from image files 1.5 * 1.6 * Main program 1.7 - * $Id: tumble.c,v 1.37 2003/03/19 07:39:55 eric Exp $ 1.8 + * $Id: tumble.c,v 1.38 2003/03/19 22:54:07 eric Exp $ 1.9 * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com> 1.10 * 1.11 * This program is free software; you can redistribute it and/or modify 1.12 @@ -30,25 +30,17 @@ 1.13 #include <string.h> 1.14 #include <unistd.h> 1.15 1.16 -#include <tiffio.h> 1.17 -#define TIFF_REVERSE_BITS 1.18 1.19 -#include "bitblt.h" 1.20 #include "semantics.h" 1.21 #include "parser.tab.h" 1.22 #include "tumble.h" 1.23 +#include "bitblt.h" 1.24 #include "pdf.h" 1.25 +#include "tumble_input.h" 1.26 1.27 1.28 #define MAX_INPUT_FILES 5000 1.29 1.30 -#define POINTS_PER_INCH 72 1.31 - 1.32 -/* page size limited by Acrobat Reader to 45 inches on a side */ 1.33 -#define PAGE_MAX_INCHES 45 1.34 -#define PAGE_MAX_POINTS (PAGE_MAX_INCHES * POINTS_PER_INCH) 1.35 - 1.36 - 1.37 typedef struct output_file_t 1.38 { 1.39 struct output_file_t *next; 1.40 @@ -60,18 +52,6 @@ 1.41 int verbose; 1.42 1.43 1.44 -typedef enum 1.45 - { 1.46 - INPUT_FILE_TYPE_NONE, 1.47 - INPUT_FILE_TYPE_TIFF, 1.48 - INPUT_FILE_TYPE_JPEG 1.49 - } input_file_type_t; 1.50 - 1.51 - 1.52 -char *in_filename; 1.53 -input_file_type_t in_type; 1.54 -FILE *in; 1.55 -TIFF *tiff_in; 1.56 output_file_t *output_files; 1.57 output_file_t *out; 1.58 1.59 @@ -79,7 +59,6 @@ 1.60 char *progname; 1.61 1.62 1.63 -bool close_tiff_input_file (void); 1.64 bool close_pdf_output_files (void); 1.65 1.66 1.67 @@ -126,142 +105,6 @@ 1.68 } 1.69 1.70 1.71 -bool close_tiff_input_file (void) 1.72 -{ 1.73 - TIFFClose (tiff_in); 1.74 - return (1); 1.75 -} 1.76 - 1.77 - 1.78 -bool open_tiff_input_file (FILE *f, char *name) 1.79 -{ 1.80 - tiff_in = TIFFFdOpen (fileno (f), name, "r"); 1.81 - if (! tiff_in) 1.82 - { 1.83 - fprintf (stderr, "can't open input file '%s'\n", name); 1.84 - free (in_filename); 1.85 - return (0); 1.86 - } 1.87 - in_type = INPUT_FILE_TYPE_TIFF; 1.88 - return (1); 1.89 -} 1.90 - 1.91 - 1.92 -bool close_jpeg_input_file (void) 1.93 -{ 1.94 - return (1); 1.95 -} 1.96 - 1.97 - 1.98 -bool open_jpeg_input_file (FILE *f, char *name) 1.99 -{ 1.100 - in_type = INPUT_FILE_TYPE_JPEG; 1.101 - return (1); 1.102 -} 1.103 - 1.104 - 1.105 -bool open_input_file (char *name) 1.106 -{ 1.107 - bool result; 1.108 - uint8_t buf [2]; 1.109 - size_t l; 1.110 - 1.111 - if (in) 1.112 - { 1.113 - if (strcmp (name, in_filename) == 0) 1.114 - return (1); 1.115 - close_input_file (); 1.116 - } 1.117 - in_filename = strdup (name); 1.118 - if (! in_filename) 1.119 - { 1.120 - fprintf (stderr, "can't strdup input filename '%s'\n", name); 1.121 - return (0); 1.122 - } 1.123 - 1.124 - in = fopen (name, "rb"); 1.125 - if (! in) 1.126 - return (0); 1.127 - 1.128 - l = fread (& buf [0], 1, sizeof (buf), in); 1.129 - if (l != sizeof (buf)) 1.130 - return (0); 1.131 - 1.132 - rewind (in); 1.133 - 1.134 - if ((buf [0] == 0x49) && (buf [1] == 0x49)) 1.135 - result = open_tiff_input_file (in, name); 1.136 - else if ((buf [0] == 0xff) && (buf [1] == 0xd8)) 1.137 - result = open_jpeg_input_file (in, name); 1.138 - else 1.139 - { 1.140 - fprintf (stderr, "unrecognized file header in file '%s'\n", name); 1.141 - result = 0; 1.142 - } 1.143 - if (! result) 1.144 - { 1.145 - if (in) 1.146 - fclose (in); 1.147 - in = NULL; 1.148 - in_type = INPUT_FILE_TYPE_NONE; 1.149 - } 1.150 - return (result); 1.151 -} 1.152 - 1.153 - 1.154 -bool close_input_file (void) 1.155 -{ 1.156 - bool result; 1.157 - 1.158 - switch (in_type) 1.159 - { 1.160 - case INPUT_FILE_TYPE_NONE: 1.161 - return (1); 1.162 - case INPUT_FILE_TYPE_TIFF: 1.163 - result = close_tiff_input_file (); 1.164 - break; 1.165 - case INPUT_FILE_TYPE_JPEG: 1.166 - result = close_jpeg_input_file (); 1.167 - break; 1.168 - default: 1.169 - fatal (3, "internal error: bad input file type\n"); 1.170 - } 1.171 - 1.172 - if (in_filename) 1.173 - free (in_filename); 1.174 - fclose (in); 1.175 - in = NULL; 1.176 - 1.177 - return (result); 1.178 -} 1.179 - 1.180 - 1.181 -bool last_tiff_input_page (void) 1.182 -{ 1.183 - return (TIFFLastDirectory (tiff_in)); 1.184 -} 1.185 - 1.186 - 1.187 -bool last_jpeg_input_page (void) 1.188 -{ 1.189 - return (1); 1.190 -} 1.191 - 1.192 - 1.193 -bool last_input_page (void) 1.194 -{ 1.195 - switch (in_type) 1.196 - { 1.197 - case INPUT_FILE_TYPE_TIFF: 1.198 - return (last_tiff_input_page ()); 1.199 - case INPUT_FILE_TYPE_JPEG: 1.200 - return (last_jpeg_input_page ()); 1.201 - default: 1.202 - fatal (3, "internal error: bad input file type\n"); 1.203 - } 1.204 -} 1.205 - 1.206 - 1.207 bool close_pdf_output_files (void) 1.208 { 1.209 output_file_t *o, *n; 1.210 @@ -335,287 +178,23 @@ 1.211 } 1.212 1.213 1.214 -/* frees original! */ 1.215 -static Bitmap *resize_bitmap (Bitmap *src, 1.216 - double x_resolution, 1.217 - double y_resolution, 1.218 - input_attributes_t input_attributes) 1.219 -{ 1.220 - Rect src_rect; 1.221 - Point dest_min; 1.222 - Bitmap *dest; 1.223 - 1.224 - int width_pixels = input_attributes.page_size.width * x_resolution; 1.225 - int height_pixels = input_attributes.page_size.height * y_resolution; 1.226 - 1.227 - src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2; 1.228 - src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2; 1.229 - src_rect.max.x = src_rect.min.x + width_pixels; 1.230 - src_rect.max.y = src_rect.min.y + height_pixels; 1.231 - 1.232 - dest_min.x = 0; 1.233 - dest_min.y = 0; 1.234 - 1.235 - dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0); 1.236 - free_bitmap (src); 1.237 - return (dest); 1.238 -} 1.239 - 1.240 - 1.241 -/* "in place" rotation */ 1.242 -static void rotate_bitmap (Bitmap *src, 1.243 - input_attributes_t input_attributes) 1.244 -{ 1.245 - switch (input_attributes.rotation) 1.246 - { 1.247 - case 0: break; 1.248 - case 90: rot_90 (src); break; 1.249 - case 180: rot_180 (src); break; 1.250 - case 270: rot_270 (src); break; 1.251 - default: 1.252 - fprintf (stderr, "rotation must be 0, 90, 180, or 270\n"); 1.253 - } 1.254 -} 1.255 - 1.256 - 1.257 -#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0) 1.258 - 1.259 - 1.260 -static pdf_page_handle process_tiff_page (int image, /* range 1 .. n */ 1.261 - input_attributes_t input_attributes) 1.262 -{ 1.263 - uint32_t image_length, image_width; 1.264 - uint32_t dest_image_length, dest_image_width; 1.265 -#ifdef CHECK_DEPTH 1.266 - uint32_t image_depth; 1.267 -#endif 1.268 - 1.269 - uint16_t samples_per_pixel; 1.270 - uint16_t bits_per_sample; 1.271 - uint16_t planar_config; 1.272 - 1.273 - uint16_t resolution_unit; 1.274 - float x_resolution, y_resolution; 1.275 - double dest_x_resolution, dest_y_resolution; 1.276 - 1.277 - double width_points, height_points; /* really 1/72 inch units rather than 1.278 - points */ 1.279 - 1.280 - Rect rect; 1.281 - Bitmap *bitmap = NULL; 1.282 - 1.283 - int row; 1.284 - 1.285 - pdf_page_handle page = NULL; 1.286 - 1.287 - if (! TIFFSetDirectory (tiff_in, image - 1)) 1.288 - { 1.289 - fprintf (stderr, "can't find page %d of input file\n", image); 1.290 - goto fail; 1.291 - } 1.292 - if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_length)) 1.293 - { 1.294 - fprintf (stderr, "can't get image length\n"); 1.295 - goto fail; 1.296 - } 1.297 - if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width)) 1.298 - { 1.299 - fprintf (stderr, "can't get image width\n"); 1.300 - goto fail; 1.301 - } 1.302 - 1.303 - if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel)) 1.304 - { 1.305 - fprintf (stderr, "can't get samples per pixel\n"); 1.306 - goto fail; 1.307 - } 1.308 - 1.309 -#ifdef CHECK_DEPTH 1.310 - if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth)) 1.311 - { 1.312 - fprintf (stderr, "can't get image depth\n"); 1.313 - goto fail; 1.314 - } 1.315 -#endif 1.316 - 1.317 - if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample)) 1.318 - { 1.319 - fprintf (stderr, "can't get bits per sample\n"); 1.320 - goto fail; 1.321 - } 1.322 - 1.323 - if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config)) 1.324 - planar_config = 1; 1.325 - 1.326 - if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit)) 1.327 - resolution_unit = 2; 1.328 - if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution)) 1.329 - x_resolution = 300; 1.330 - if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution)) 1.331 - y_resolution = 300; 1.332 - 1.333 - if (samples_per_pixel != 1) 1.334 - { 1.335 - fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel); 1.336 - goto fail; 1.337 - } 1.338 - 1.339 -#ifdef CHECK_DEPTH 1.340 - if (image_depth != 1) 1.341 - { 1.342 - fprintf (stderr, "image depth %u, must be 1\n", image_depth); 1.343 - goto fail; 1.344 - } 1.345 -#endif 1.346 - 1.347 - if (bits_per_sample != 1) 1.348 - { 1.349 - fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample); 1.350 - goto fail; 1.351 - } 1.352 - 1.353 - if (planar_config != 1) 1.354 - { 1.355 - fprintf (stderr, "planar config %u, must be 1\n", planar_config); 1.356 - goto fail; 1.357 - } 1.358 - 1.359 - if (input_attributes.has_resolution) 1.360 - { 1.361 - x_resolution = input_attributes.x_resolution; 1.362 - y_resolution = input_attributes.y_resolution; 1.363 - } 1.364 - 1.365 - if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270)) 1.366 - { 1.367 - dest_image_width = image_length; 1.368 - dest_image_length = image_width; 1.369 - dest_x_resolution = y_resolution; 1.370 - dest_y_resolution = x_resolution; 1.371 - SWAP (double, width_points, height_points); /* $$$ not yet set!!! */ 1.372 - } 1.373 - else 1.374 - { 1.375 - dest_image_width = image_width; 1.376 - dest_image_length = image_length; 1.377 - dest_x_resolution = x_resolution; 1.378 - dest_y_resolution = y_resolution; 1.379 - } 1.380 - 1.381 - rect.min.x = 0; 1.382 - rect.min.y = 0; 1.383 - rect.max.x = image_width; 1.384 - rect.max.y = image_length; 1.385 - 1.386 - bitmap = create_bitmap (& rect); 1.387 - 1.388 - if (! bitmap) 1.389 - { 1.390 - fprintf (stderr, "can't allocate bitmap\n"); 1.391 - goto fail; 1.392 - } 1.393 - 1.394 - for (row = 0; row < image_length; row++) 1.395 - if (1 != TIFFReadScanline (tiff_in, 1.396 - bitmap->bits + row * bitmap->row_words, 1.397 - row, 1.398 - 0)) 1.399 - { 1.400 - fprintf (stderr, "can't read TIFF scanline\n"); 1.401 - goto fail; 1.402 - } 1.403 - 1.404 -#ifdef TIFF_REVERSE_BITS 1.405 - reverse_bits ((uint8_t *) bitmap->bits, 1.406 - image_length * bitmap->row_words * sizeof (word_t)); 1.407 -#endif /* TIFF_REVERSE_BITS */ 1.408 - 1.409 -#if 0 1.410 - if (input_attributes.has_page_size) 1.411 - bitmap = resize_bitmap (bitmap, 1.412 - x_resolution, 1.413 - y_resolution, 1.414 - input_attributes); 1.415 -#endif 1.416 - 1.417 - rotate_bitmap (bitmap, 1.418 - input_attributes); 1.419 - 1.420 - width_points = (rect_width (& bitmap->rect) / dest_x_resolution) * POINTS_PER_INCH; 1.421 - height_points = (rect_height (& bitmap->rect) / dest_y_resolution) * POINTS_PER_INCH; 1.422 - 1.423 - if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS)) 1.424 - { 1.425 - fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); 1.426 - goto fail; 1.427 - } 1.428 - 1.429 - page = pdf_new_page (out->pdf, width_points, height_points); 1.430 - 1.431 -#if 0 1.432 - pdf_write_text (page); 1.433 -#else 1.434 - pdf_write_g4_fax_image (page, 1.435 - 0, 0, /* x, y */ 1.436 - width_points, height_points, 1.437 - bitmap, 1.438 - 0, /* ImageMask */ 1.439 - 0, 0, 0, /* r, g, b */ 1.440 - 0); /* BlackIs1 */ 1.441 -#endif 1.442 - 1.443 - if (bitmap) 1.444 - free_bitmap (bitmap); 1.445 - return (page); 1.446 - 1.447 - fail: 1.448 - if (bitmap) 1.449 - free_bitmap (bitmap); 1.450 - 1.451 - return (NULL); 1.452 -} 1.453 - 1.454 - 1.455 -pdf_page_handle process_jpeg_page (int image, /* range 1 .. n */ 1.456 - input_attributes_t input_attributes) 1.457 -{ 1.458 - pdf_page_handle page; 1.459 - double width_points, height_points; /* really 1/72 inch units rather than 1.460 - points */ 1.461 - 1.462 - /* $$$ need to get these from somewhere else, hardcoded for now */ 1.463 - width_points = 4 * 72.0; 1.464 - height_points = 4 * 72.0; 1.465 - 1.466 - page = pdf_new_page (out->pdf, width_points, height_points); 1.467 - 1.468 - pdf_write_jpeg_image (page, 1.469 - 0, 0, /* x, y */ 1.470 - width_points, height_points, 1.471 - in); 1.472 - 1.473 - return (page); 1.474 -} 1.475 - 1.476 - 1.477 bool process_page (int image, /* range 1 .. n */ 1.478 input_attributes_t input_attributes, 1.479 bookmark_t *bookmarks, 1.480 page_label_t *page_label) 1.481 { 1.482 pdf_page_handle page; 1.483 + image_info_t image_info; 1.484 + 1.485 + if (! get_image_info (image, input_attributes, & image_info)) 1.486 + return (0); 1.487 1.488 - switch (in_type) 1.489 - { 1.490 - case INPUT_FILE_TYPE_TIFF: 1.491 - page = process_tiff_page (image, input_attributes); 1.492 - break; 1.493 - case INPUT_FILE_TYPE_JPEG: 1.494 - page = process_jpeg_page (image, input_attributes); 1.495 - break; 1.496 - default: 1.497 - fatal (3, "internal error: bad input file type\n"); 1.498 - } 1.499 + page = pdf_new_page (out->pdf, 1.500 + image_info.width_points, 1.501 + image_info.height_points); 1.502 + 1.503 + if (! process_image (image, input_attributes, & image_info, page)) 1.504 + return (0); 1.505 1.506 while (bookmarks) 1.507 { 1.508 @@ -769,6 +348,9 @@ 1.509 1.510 pdf_init (); 1.511 1.512 + init_tiff_handler (); 1.513 + init_jpeg_handler (); 1.514 + 1.515 while (--argc) 1.516 { 1.517 if (argv [1][0] == '-')