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