tumble.c

changeset 141
752599b50ff3
parent 139
ec2a06d8a2a6
child 149
460c336ec8d7
     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] == '-')