more JPEG support. added input file handler API.

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

author
eric
date
Thu, 20 Mar 2003 06:54:08 +0000
changeset 141
752599b50ff3
parent 140
3fe049d83e22
child 142
cfa664f3129c

more JPEG support. added input file handler API.

Makefile file | annotate | diff | revisions
README file | annotate | diff | revisions
pdf.h file | annotate | diff | revisions
tumble.c file | annotate | diff | revisions
tumble.h file | annotate | diff | revisions
tumble_input.c file | annotate | diff | revisions
tumble_input.h file | annotate | diff | revisions
tumble_jpeg.c file | annotate | diff | revisions
tumble_tiff.c file | annotate | diff | revisions
     1.1 diff -r 3fe049d83e22 -r 752599b50ff3 Makefile
     1.2 --- a/Makefile	Thu Mar 20 01:08:05 2003 +0000
     1.3 +++ b/Makefile	Thu Mar 20 06:54:08 2003 +0000
     1.4 @@ -1,6 +1,6 @@
     1.5  # tumble: build a PDF file from image files
     1.6  # Makefile
     1.7 -# $Id: Makefile,v 1.34 2003/03/16 07:40:00 eric Exp $
     1.8 +# $Id: Makefile,v 1.35 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 @@ -23,7 +23,7 @@
    1.13  # "0" value is considered true by make, so to disable conditionals comment
    1.14  # them out or set them to a null string.
    1.15  
    1.16 -#DEBUG=1
    1.17 +DEBUG=1
    1.18  #EFENCE=1
    1.19  #STATIC=1
    1.20  
    1.21 @@ -57,19 +57,20 @@
    1.22  # let me know why so I can improve this Makefile.
    1.23  # -----------------------------------------------------------------------------
    1.24  
    1.25 -VERSION = 0.28
    1.26 +VERSION = 0.29
    1.27  
    1.28  PACKAGE = tumble
    1.29  
    1.30  TARGETS = tumble
    1.31  
    1.32  CSRCS = tumble.c semantics.c \
    1.33 +	tumble_input.c tumble_tiff.c tumble_jpeg.c \
    1.34  	bitblt.c bitblt_table_gen.c bitblt_g4.c g4_table_gen.c \
    1.35  	pdf.c pdf_util.c pdf_prim.c pdf_name_tree.c \
    1.36  	pdf_bookmark.c pdf_page_label.c \
    1.37  	pdf_text.c pdf_g4.c pdf_jpeg.c
    1.38  OSRCS = scanner.l parser.y
    1.39 -HDRS = tumble.h semantics.h bitblt.h bitblt_tables.h \
    1.40 +HDRS = tumble.h tumble_input.h semantics.h bitblt.h bitblt_tables.h \
    1.41  	pdf.h pdf_private.h pdf_util.h pdf_prim.h pdf_name_tree.h
    1.42  MISC = COPYING README INSTALL Makefile
    1.43  
    1.44 @@ -90,7 +91,9 @@
    1.45  all: $(TARGETS) $(TEST_TARGETS)
    1.46  
    1.47  
    1.48 -tumble: tumble.o scanner.o semantics.o parser.tab.o \
    1.49 +tumble: tumble.o semantics.o \
    1.50 +		tumble_input.o tumble_tiff.o tumble_jpeg.o \
    1.51 +		scanner.o parser.tab.o \
    1.52  		bitblt.o bitblt_g4.o bitblt_tables.o g4_tables.o \
    1.53  		pdf.o pdf_util.o pdf_prim.o pdf_name_tree.o \
    1.54  		pdf_bookmark.o pdf_page_label.o \
     2.1 diff -r 3fe049d83e22 -r 752599b50ff3 README
     2.2 --- a/README	Thu Mar 20 01:08:05 2003 +0000
     2.3 +++ b/README	Thu Mar 20 06:54:08 2003 +0000
     2.4 @@ -1,15 +1,14 @@
     2.5  tumble: build a PDF file from image files
     2.6  Copyright 2003 Eric Smith <eric@brouhaha.com>
     2.7 -$Id: README,v 1.1 2003/03/16 07:37:16 eric Exp $
     2.8 +$Id: README,v 1.2 2003/03/19 22:54:07 eric Exp $
     2.9  
    2.10  Tumble is a utility to construct PDF files from one or more image
    2.11 -files.  Currently the only input image format supported is black &
    2.12 -white TIFF files, which may be either single- or multi-page files.  In
    2.13 -the future additional file formats will be supported, including gray
    2.14 -scale and color.  Black and white images will be encoded in the PDF
    2.15 -output using lossless Group 4 fax compression (ITU-T recommendation
    2.16 -T.6).  This provides a very good compression ratio for text and line
    2.17 -art.
    2.18 +files.  Supported input image file formats are JPEG, and black and
    2.19 +white TIFF (single- or multi-page).  Black and white images will be
    2.20 +encoded in the PDF output using lossless Group 4 fax compression
    2.21 +(ITU-T recommendation T.6).  This provides a very good compression
    2.22 +ratio for text and line art.  JPEG images will be preserved with the
    2.23 +original coding.
    2.24  
    2.25  The current version of Tumble will only work on little-endian systems,
    2.26  such as x86, VAX, and Alpha.  The byte order dependencies will be fixed
    2.27 @@ -21,7 +20,7 @@
    2.28  
    2.29  The general command line syntax is:
    2.30  
    2.31 -    tumble [options] <input.tif>... -o <output.pdf>
    2.32 +    tumble [options] <input>... -o <output.pdf>
    2.33  
    2.34  The options in this mode are:
    2.35  
     3.1 diff -r 3fe049d83e22 -r 752599b50ff3 pdf.h
     3.2 --- a/pdf.h	Thu Mar 20 01:08:05 2003 +0000
     3.3 +++ b/pdf.h	Thu Mar 20 06:54:08 2003 +0000
     3.4 @@ -2,7 +2,7 @@
     3.5   * tumble: build a PDF file from image files
     3.6   *
     3.7   * PDF routines
     3.8 - * $Id: pdf.h,v 1.11 2003/03/14 00:57:40 eric Exp $
     3.9 + * $Id: pdf.h,v 1.12 2003/03/19 22:54:07 eric Exp $
    3.10   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    3.11   *
    3.12   * This program is free software; you can redistribute it and/or modify
    3.13 @@ -22,6 +22,13 @@
    3.14   */
    3.15  
    3.16  
    3.17 +#define POINTS_PER_INCH 72
    3.18 +
    3.19 +/* page size limited by Acrobat Reader to 45 inches on a side */
    3.20 +#define PAGE_MAX_INCHES 45
    3.21 +#define PAGE_MAX_POINTS (PAGE_MAX_INCHES * POINTS_PER_INCH)
    3.22 +
    3.23 +
    3.24  typedef struct pdf_file *pdf_file_handle;
    3.25  
    3.26  typedef struct pdf_page *pdf_page_handle;
     4.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble.c
     4.2 --- a/tumble.c	Thu Mar 20 01:08:05 2003 +0000
     4.3 +++ b/tumble.c	Thu Mar 20 06:54:08 2003 +0000
     4.4 @@ -2,7 +2,7 @@
     4.5   * tumble: build a PDF file from image files
     4.6   *
     4.7   * Main program
     4.8 - * $Id: tumble.c,v 1.37 2003/03/19 07:39:55 eric Exp $
     4.9 + * $Id: tumble.c,v 1.38 2003/03/19 22:54:07 eric Exp $
    4.10   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    4.11   *
    4.12   * This program is free software; you can redistribute it and/or modify
    4.13 @@ -30,25 +30,17 @@
    4.14  #include <string.h>
    4.15  #include <unistd.h>
    4.16  
    4.17 -#include <tiffio.h>
    4.18 -#define TIFF_REVERSE_BITS
    4.19  
    4.20 -#include "bitblt.h"
    4.21  #include "semantics.h"
    4.22  #include "parser.tab.h"
    4.23  #include "tumble.h"
    4.24 +#include "bitblt.h"
    4.25  #include "pdf.h"
    4.26 +#include "tumble_input.h"
    4.27  
    4.28  
    4.29  #define MAX_INPUT_FILES 5000
    4.30  
    4.31 -#define POINTS_PER_INCH 72
    4.32 -
    4.33 -/* page size limited by Acrobat Reader to 45 inches on a side */
    4.34 -#define PAGE_MAX_INCHES 45
    4.35 -#define PAGE_MAX_POINTS (PAGE_MAX_INCHES * POINTS_PER_INCH)
    4.36 -
    4.37 -
    4.38  typedef struct output_file_t
    4.39  {
    4.40    struct output_file_t *next;
    4.41 @@ -60,18 +52,6 @@
    4.42  int verbose;
    4.43  
    4.44  
    4.45 -typedef enum
    4.46 -  {
    4.47 -    INPUT_FILE_TYPE_NONE,
    4.48 -    INPUT_FILE_TYPE_TIFF,
    4.49 -    INPUT_FILE_TYPE_JPEG
    4.50 -  } input_file_type_t;
    4.51 -
    4.52 -
    4.53 -char *in_filename;
    4.54 -input_file_type_t in_type;
    4.55 -FILE *in;
    4.56 -TIFF *tiff_in;
    4.57  output_file_t *output_files;
    4.58  output_file_t *out;
    4.59  
    4.60 @@ -79,7 +59,6 @@
    4.61  char *progname;
    4.62  
    4.63  
    4.64 -bool close_tiff_input_file (void);
    4.65  bool close_pdf_output_files (void);
    4.66  
    4.67  
    4.68 @@ -126,142 +105,6 @@
    4.69  }
    4.70  
    4.71  
    4.72 -bool close_tiff_input_file (void)
    4.73 -{
    4.74 -  TIFFClose (tiff_in);
    4.75 -  return (1);
    4.76 -}
    4.77 -
    4.78 -
    4.79 -bool open_tiff_input_file (FILE *f, char *name)
    4.80 -{
    4.81 -  tiff_in = TIFFFdOpen (fileno (f), name, "r");
    4.82 -  if (! tiff_in)
    4.83 -    {
    4.84 -      fprintf (stderr, "can't open input file '%s'\n", name);
    4.85 -      free (in_filename);
    4.86 -      return (0);
    4.87 -    }
    4.88 -  in_type = INPUT_FILE_TYPE_TIFF;
    4.89 -  return (1);
    4.90 -}
    4.91 -
    4.92 -
    4.93 -bool close_jpeg_input_file (void)
    4.94 -{
    4.95 -  return (1);
    4.96 -}
    4.97 -
    4.98 -
    4.99 -bool open_jpeg_input_file (FILE *f, char *name)
   4.100 -{
   4.101 -  in_type = INPUT_FILE_TYPE_JPEG;
   4.102 -  return (1);
   4.103 -}
   4.104 -
   4.105 -
   4.106 -bool open_input_file (char *name)
   4.107 -{
   4.108 -  bool result;
   4.109 -  uint8_t buf [2];
   4.110 -  size_t l;
   4.111 -
   4.112 -  if (in)
   4.113 -    {
   4.114 -      if (strcmp (name, in_filename) == 0)
   4.115 -	return (1);
   4.116 -      close_input_file ();
   4.117 -    }
   4.118 -  in_filename = strdup (name);
   4.119 -  if (! in_filename)
   4.120 -    {
   4.121 -      fprintf (stderr, "can't strdup input filename '%s'\n", name);
   4.122 -      return (0);
   4.123 -    }
   4.124 -
   4.125 -  in = fopen (name, "rb");
   4.126 -  if (! in)
   4.127 -    return (0);
   4.128 -
   4.129 -  l = fread (& buf [0], 1, sizeof (buf), in);
   4.130 -  if (l != sizeof (buf))
   4.131 -    return (0);
   4.132 -
   4.133 -  rewind (in);
   4.134 -
   4.135 -  if ((buf [0] == 0x49) && (buf [1] == 0x49))
   4.136 -    result = open_tiff_input_file (in, name);
   4.137 -  else if ((buf [0] == 0xff) && (buf [1] == 0xd8))
   4.138 -    result = open_jpeg_input_file (in, name);
   4.139 -  else
   4.140 -    {
   4.141 -      fprintf (stderr, "unrecognized file header in file '%s'\n", name);
   4.142 -      result = 0;
   4.143 -    }
   4.144 -  if (! result)
   4.145 -    {
   4.146 -      if (in)
   4.147 -	fclose (in);
   4.148 -      in = NULL;
   4.149 -      in_type = INPUT_FILE_TYPE_NONE;
   4.150 -    }
   4.151 -  return (result);
   4.152 -}
   4.153 -
   4.154 -
   4.155 -bool close_input_file (void)
   4.156 -{
   4.157 -  bool result;
   4.158 -
   4.159 -  switch (in_type)
   4.160 -    {
   4.161 -    case INPUT_FILE_TYPE_NONE:
   4.162 -      return (1);
   4.163 -    case INPUT_FILE_TYPE_TIFF:
   4.164 -      result = close_tiff_input_file ();
   4.165 -      break;
   4.166 -    case INPUT_FILE_TYPE_JPEG:
   4.167 -      result = close_jpeg_input_file ();
   4.168 -      break;
   4.169 -    default:
   4.170 -      fatal (3, "internal error: bad input file type\n");
   4.171 -    }
   4.172 -
   4.173 -  if (in_filename)
   4.174 -    free (in_filename);
   4.175 -  fclose (in);
   4.176 -  in = NULL;
   4.177 -
   4.178 -  return (result);
   4.179 -}
   4.180 -
   4.181 -
   4.182 -bool last_tiff_input_page (void)
   4.183 -{
   4.184 -  return (TIFFLastDirectory (tiff_in));
   4.185 -}
   4.186 -
   4.187 -
   4.188 -bool last_jpeg_input_page (void)
   4.189 -{
   4.190 -  return (1);
   4.191 -}
   4.192 -
   4.193 -
   4.194 -bool last_input_page (void)
   4.195 -{
   4.196 -  switch (in_type)
   4.197 -    {
   4.198 -    case INPUT_FILE_TYPE_TIFF:
   4.199 -      return (last_tiff_input_page ());
   4.200 -    case INPUT_FILE_TYPE_JPEG:
   4.201 -      return (last_jpeg_input_page ());
   4.202 -    default:
   4.203 -      fatal (3, "internal error: bad input file type\n");
   4.204 -    }
   4.205 -}
   4.206 -
   4.207 -
   4.208  bool close_pdf_output_files (void)
   4.209  {
   4.210    output_file_t *o, *n;
   4.211 @@ -335,287 +178,23 @@
   4.212  }
   4.213  
   4.214  
   4.215 -/* frees original! */
   4.216 -static Bitmap *resize_bitmap (Bitmap *src,
   4.217 -			      double x_resolution,
   4.218 -			      double y_resolution,
   4.219 -			      input_attributes_t input_attributes)
   4.220 -{
   4.221 -  Rect src_rect;
   4.222 -  Point dest_min;
   4.223 -  Bitmap *dest;
   4.224 -
   4.225 -  int width_pixels = input_attributes.page_size.width * x_resolution;
   4.226 -  int height_pixels = input_attributes.page_size.height * y_resolution;
   4.227 -
   4.228 -  src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
   4.229 -  src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
   4.230 -  src_rect.max.x = src_rect.min.x + width_pixels;
   4.231 -  src_rect.max.y = src_rect.min.y + height_pixels;
   4.232 -
   4.233 -  dest_min.x = 0;
   4.234 -  dest_min.y = 0;
   4.235 -
   4.236 -  dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
   4.237 -  free_bitmap (src);
   4.238 -  return (dest);
   4.239 -}
   4.240 -
   4.241 -
   4.242 -/* "in place" rotation */
   4.243 -static void rotate_bitmap (Bitmap *src,
   4.244 -			   input_attributes_t input_attributes)
   4.245 -{
   4.246 -  switch (input_attributes.rotation)
   4.247 -    {
   4.248 -    case 0: break;
   4.249 -    case 90: rot_90 (src); break;
   4.250 -    case 180: rot_180 (src); break;
   4.251 -    case 270: rot_270 (src); break;
   4.252 -    default:
   4.253 -      fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
   4.254 -    }
   4.255 -}
   4.256 -
   4.257 -
   4.258 -#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
   4.259 -
   4.260 -
   4.261 -static pdf_page_handle process_tiff_page (int image,  /* range 1 .. n */
   4.262 -					  input_attributes_t input_attributes)
   4.263 -{
   4.264 -  uint32_t image_length, image_width;
   4.265 -  uint32_t dest_image_length, dest_image_width;
   4.266 -#ifdef CHECK_DEPTH
   4.267 -  uint32_t image_depth;
   4.268 -#endif
   4.269 -
   4.270 -  uint16_t samples_per_pixel;
   4.271 -  uint16_t bits_per_sample;
   4.272 -  uint16_t planar_config;
   4.273 -
   4.274 -  uint16_t resolution_unit;
   4.275 -  float x_resolution, y_resolution;
   4.276 -  double dest_x_resolution, dest_y_resolution;
   4.277 -
   4.278 -  double width_points, height_points;  /* really 1/72 inch units rather than
   4.279 -					  points */
   4.280 -
   4.281 -  Rect rect;
   4.282 -  Bitmap *bitmap = NULL;
   4.283 -
   4.284 -  int row;
   4.285 -
   4.286 -  pdf_page_handle page = NULL;
   4.287 -
   4.288 -  if (! TIFFSetDirectory (tiff_in, image - 1))
   4.289 -    {
   4.290 -      fprintf (stderr, "can't find page %d of input file\n", image);
   4.291 -      goto fail;
   4.292 -    }
   4.293 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_length))
   4.294 -    {
   4.295 -      fprintf (stderr, "can't get image length\n");
   4.296 -      goto fail;
   4.297 -    }
   4.298 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
   4.299 -    {
   4.300 -      fprintf (stderr, "can't get image width\n");
   4.301 -      goto fail;
   4.302 -    }
   4.303 -
   4.304 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
   4.305 -    {
   4.306 -      fprintf (stderr, "can't get samples per pixel\n");
   4.307 -      goto fail;
   4.308 -    }
   4.309 -
   4.310 -#ifdef CHECK_DEPTH
   4.311 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
   4.312 -    {
   4.313 -      fprintf (stderr, "can't get image depth\n");
   4.314 -      goto fail;
   4.315 -    }
   4.316 -#endif
   4.317 -
   4.318 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
   4.319 -    {
   4.320 -      fprintf (stderr, "can't get bits per sample\n");
   4.321 -      goto fail;
   4.322 -    }
   4.323 -
   4.324 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
   4.325 -    planar_config = 1;
   4.326 -
   4.327 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
   4.328 -    resolution_unit = 2;
   4.329 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
   4.330 -    x_resolution = 300;
   4.331 -  if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
   4.332 -    y_resolution = 300;
   4.333 -
   4.334 -  if (samples_per_pixel != 1)
   4.335 -    {
   4.336 -      fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
   4.337 -      goto fail;
   4.338 -    }
   4.339 -
   4.340 -#ifdef CHECK_DEPTH
   4.341 -  if (image_depth != 1)
   4.342 -    {
   4.343 -      fprintf (stderr, "image depth %u, must be 1\n", image_depth);
   4.344 -      goto fail;
   4.345 -    }
   4.346 -#endif
   4.347 -
   4.348 -  if (bits_per_sample != 1)
   4.349 -    {
   4.350 -      fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
   4.351 -      goto fail;
   4.352 -    }
   4.353 -
   4.354 -  if (planar_config != 1)
   4.355 -    {
   4.356 -      fprintf (stderr, "planar config %u, must be 1\n", planar_config);
   4.357 -      goto fail;
   4.358 -    }
   4.359 -
   4.360 -  if (input_attributes.has_resolution)
   4.361 -    {
   4.362 -      x_resolution = input_attributes.x_resolution;
   4.363 -      y_resolution = input_attributes.y_resolution;
   4.364 -    }
   4.365 -
   4.366 -  if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   4.367 -    {
   4.368 -      dest_image_width  = image_length;
   4.369 -      dest_image_length = image_width;
   4.370 -      dest_x_resolution = y_resolution;
   4.371 -      dest_y_resolution = x_resolution;
   4.372 -      SWAP (double, width_points, height_points);  /* $$$ not yet set!!! */
   4.373 -    }
   4.374 -  else
   4.375 -    {
   4.376 -      dest_image_width = image_width;
   4.377 -      dest_image_length = image_length;
   4.378 -      dest_x_resolution = x_resolution;
   4.379 -      dest_y_resolution = y_resolution;
   4.380 -    }
   4.381 -
   4.382 -  rect.min.x = 0;
   4.383 -  rect.min.y = 0;
   4.384 -  rect.max.x = image_width;
   4.385 -  rect.max.y = image_length;
   4.386 -
   4.387 -  bitmap = create_bitmap (& rect);
   4.388 -
   4.389 -  if (! bitmap)
   4.390 -    {
   4.391 -      fprintf (stderr, "can't allocate bitmap\n");
   4.392 -      goto fail;
   4.393 -    }
   4.394 -
   4.395 -  for (row = 0; row < image_length; row++)
   4.396 -    if (1 != TIFFReadScanline (tiff_in,
   4.397 -			       bitmap->bits + row * bitmap->row_words,
   4.398 -			       row,
   4.399 -			       0))
   4.400 -      {
   4.401 -	fprintf (stderr, "can't read TIFF scanline\n");
   4.402 -	goto fail;
   4.403 -      }
   4.404 -
   4.405 -#ifdef TIFF_REVERSE_BITS
   4.406 -  reverse_bits ((uint8_t *) bitmap->bits,
   4.407 -		image_length * bitmap->row_words * sizeof (word_t));
   4.408 -#endif /* TIFF_REVERSE_BITS */
   4.409 -
   4.410 -#if 0
   4.411 -  if (input_attributes.has_page_size)
   4.412 -    bitmap = resize_bitmap (bitmap,
   4.413 -			    x_resolution,
   4.414 -			    y_resolution,
   4.415 -			    input_attributes);
   4.416 -#endif
   4.417 -
   4.418 -  rotate_bitmap (bitmap,
   4.419 -		 input_attributes);
   4.420 -
   4.421 -  width_points = (rect_width (& bitmap->rect) / dest_x_resolution) * POINTS_PER_INCH;
   4.422 -  height_points = (rect_height (& bitmap->rect) / dest_y_resolution) * POINTS_PER_INCH;
   4.423 -
   4.424 -  if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS))
   4.425 -    {
   4.426 -      fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
   4.427 -      goto fail;
   4.428 -    }
   4.429 -
   4.430 -  page = pdf_new_page (out->pdf, width_points, height_points);
   4.431 -
   4.432 -#if 0
   4.433 -  pdf_write_text (page);
   4.434 -#else
   4.435 -  pdf_write_g4_fax_image (page,
   4.436 -			  0, 0,  /* x, y */
   4.437 -			  width_points, height_points,
   4.438 -			  bitmap,
   4.439 -			  0, /* ImageMask */
   4.440 -			  0, 0, 0,  /* r, g, b */
   4.441 -			  0); /* BlackIs1 */
   4.442 -#endif
   4.443 -
   4.444 -  if (bitmap)
   4.445 -    free_bitmap (bitmap);
   4.446 -  return (page);
   4.447 -
   4.448 - fail:
   4.449 -  if (bitmap)
   4.450 -    free_bitmap (bitmap);
   4.451 -
   4.452 -  return (NULL);
   4.453 -}
   4.454 -
   4.455 -
   4.456 -pdf_page_handle process_jpeg_page (int image,  /* range 1 .. n */
   4.457 -				   input_attributes_t input_attributes)
   4.458 -{
   4.459 -  pdf_page_handle page;
   4.460 -  double width_points, height_points;  /* really 1/72 inch units rather than
   4.461 -					  points */
   4.462 -
   4.463 -  /* $$$ need to get these from somewhere else, hardcoded for now */
   4.464 -  width_points = 4 * 72.0;
   4.465 -  height_points = 4 * 72.0;
   4.466 -
   4.467 -  page = pdf_new_page (out->pdf, width_points, height_points);
   4.468 -
   4.469 -  pdf_write_jpeg_image (page,
   4.470 -			0, 0,  /* x, y */
   4.471 -			width_points, height_points,
   4.472 -			in);
   4.473 -
   4.474 -  return (page);
   4.475 -}
   4.476 -
   4.477 -
   4.478  bool process_page (int image,  /* range 1 .. n */
   4.479  		   input_attributes_t input_attributes,
   4.480  		   bookmark_t *bookmarks,
   4.481  		   page_label_t *page_label)
   4.482  {
   4.483    pdf_page_handle page;
   4.484 +  image_info_t image_info;
   4.485 +  
   4.486 +  if (! get_image_info (image, input_attributes, & image_info))
   4.487 +    return (0);
   4.488  
   4.489 -  switch (in_type)
   4.490 -    {
   4.491 -    case INPUT_FILE_TYPE_TIFF:
   4.492 -      page = process_tiff_page (image, input_attributes);
   4.493 -      break;
   4.494 -    case INPUT_FILE_TYPE_JPEG:
   4.495 -      page = process_jpeg_page (image, input_attributes);
   4.496 -      break;
   4.497 -    default:
   4.498 -      fatal (3, "internal error: bad input file type\n");
   4.499 -    }
   4.500 +  page = pdf_new_page (out->pdf,
   4.501 +		       image_info.width_points,
   4.502 +		       image_info.height_points);
   4.503 +
   4.504 +  if (! process_image (image, input_attributes, & image_info, page))
   4.505 +    return (0);
   4.506  
   4.507    while (bookmarks)
   4.508      {
   4.509 @@ -769,6 +348,9 @@
   4.510  
   4.511    pdf_init ();
   4.512  
   4.513 +  init_tiff_handler ();
   4.514 +  init_jpeg_handler ();
   4.515 +
   4.516    while (--argc)
   4.517      {
   4.518        if (argv [1][0] == '-')
     5.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble.h
     5.2 --- a/tumble.h	Thu Mar 20 01:08:05 2003 +0000
     5.3 +++ b/tumble.h	Thu Mar 20 06:54:08 2003 +0000
     5.4 @@ -1,7 +1,7 @@
     5.5  /*
     5.6   * tumble: build a PDF file from image files
     5.7   *
     5.8 - * $Id: tumble.h,v 1.16 2003/03/19 07:39:55 eric Exp $
     5.9 + * $Id: tumble.h,v 1.17 2003/03/19 22:54:07 eric Exp $
    5.10   * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    5.11   *
    5.12   * This program is free software; you can redistribute it and/or modify
    5.13 @@ -17,7 +17,8 @@
    5.14   *
    5.15   * You should have received a copy of the GNU General Public License
    5.16   * along with this program; if not, write to the Free Software
    5.17 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA */
    5.18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    5.19 + */
    5.20  
    5.21  
    5.22  extern int verbose;
     6.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble_input.c
     6.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 +++ b/tumble_input.c	Thu Mar 20 06:54:08 2003 +0000
     6.4 @@ -0,0 +1,140 @@
     6.5 +/*
     6.6 + * tumble: build a PDF file from image files
     6.7 + *
     6.8 + * Input handler dispatch
     6.9 + * $Id: tumble_input.c,v 1.1 2003/03/19 22:54:08 eric Exp $
    6.10 + * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    6.11 + *
    6.12 + * This program is free software; you can redistribute it and/or modify
    6.13 + * it under the terms of the GNU General Public License version 2 as
    6.14 + * published by the Free Software Foundation.  Note that permission is
    6.15 + * not granted to redistribute this program under the terms of any
    6.16 + * other version of the General Public License.
    6.17 + *
    6.18 + * This program is distributed in the hope that it will be useful,
    6.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.21 + * GNU General Public License for more details.
    6.22 + *
    6.23 + * You should have received a copy of the GNU General Public License
    6.24 + * along with this program; if not, write to the Free Software
    6.25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    6.26 + */
    6.27 +
    6.28 +
    6.29 +#include <stdbool.h>
    6.30 +#include <stdint.h>
    6.31 +#include <stdio.h>
    6.32 +#include <stdlib.h>
    6.33 +#include <string.h>
    6.34 +
    6.35 +
    6.36 +#include "semantics.h"
    6.37 +#include "tumble.h"
    6.38 +#include "bitblt.h"
    6.39 +#include "pdf.h"
    6.40 +#include "tumble_input.h"
    6.41 +
    6.42 +
    6.43 +#define MAX_INPUT_HANDLERS 10
    6.44 +
    6.45 +static int input_handler_count = 0;
    6.46 +
    6.47 +static input_handler_t *input_handlers [MAX_INPUT_HANDLERS];
    6.48 +
    6.49 +
    6.50 +static char *in_filename;
    6.51 +static FILE *in;
    6.52 +static input_handler_t *current_input_handler;
    6.53 +
    6.54 +
    6.55 +void install_input_handler (input_handler_t *handler)
    6.56 +{
    6.57 +  if (input_handler_count >= MAX_INPUT_HANDLERS)
    6.58 +    fprintf (stderr, "Too many input handlers, table only has room for %d\n", MAX_INPUT_HANDLERS);
    6.59 +  else
    6.60 +    input_handlers [input_handler_count++] = handler;
    6.61 +}
    6.62 +
    6.63 +
    6.64 +bool open_input_file (char *name)
    6.65 +{
    6.66 +  int i;
    6.67 +
    6.68 +  if (in)
    6.69 +    {
    6.70 +      if (strcmp (name, in_filename) == 0)
    6.71 +	return (1);
    6.72 +      close_input_file ();
    6.73 +    }
    6.74 +  in_filename = strdup (name);
    6.75 +  if (! in_filename)
    6.76 +    {
    6.77 +      fprintf (stderr, "can't strdup input filename '%s'\n", name);
    6.78 +      goto fail;
    6.79 +    }
    6.80 +
    6.81 +  in = fopen (name, "rb");
    6.82 +  if (! in)
    6.83 +    goto fail;
    6.84 +
    6.85 +  for (i = 0; i < input_handler_count; i++)
    6.86 +    {
    6.87 +      if (input_handlers [i]->open_input_file (in, name))
    6.88 +	break;
    6.89 +    }
    6.90 +  if (i >= input_handler_count)
    6.91 +    {
    6.92 +      fprintf (stderr, "unrecognized format for input file '%s'\n", name);
    6.93 +      goto fail;
    6.94 +    }
    6.95 +  current_input_handler = input_handlers [i];
    6.96 +  return (1);
    6.97 +
    6.98 + fail:
    6.99 +  if (in)
   6.100 +    fclose (in);
   6.101 +  in = NULL;
   6.102 +  return (0);
   6.103 +}
   6.104 +
   6.105 +
   6.106 +bool close_input_file (void)
   6.107 +{
   6.108 +  bool result;
   6.109 +
   6.110 +  result = current_input_handler->close_input_file ();
   6.111 +  if (in_filename)
   6.112 +    free (in_filename);
   6.113 +  fclose (in);
   6.114 +  in = NULL;
   6.115 +
   6.116 +  return (result);
   6.117 +}
   6.118 +
   6.119 +
   6.120 +bool last_input_page (void)
   6.121 +{
   6.122 +  return (current_input_handler->last_input_page ());
   6.123 +}
   6.124 +
   6.125 +
   6.126 +bool get_image_info (int image,
   6.127 +		     input_attributes_t input_attributes,
   6.128 +		     image_info_t *image_info)
   6.129 +{
   6.130 +  return (current_input_handler->get_image_info (image,
   6.131 +						 input_attributes,
   6.132 +						 image_info));
   6.133 +}
   6.134 +
   6.135 +bool process_image (int image,
   6.136 +		    input_attributes_t input_attributes,
   6.137 +		    image_info_t *image_info,
   6.138 +		    pdf_page_handle page)
   6.139 +{
   6.140 +  return (current_input_handler->process_image (image,
   6.141 +						input_attributes,
   6.142 +						image_info,
   6.143 +						page));
   6.144 +}
     7.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble_input.h
     7.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 +++ b/tumble_input.h	Thu Mar 20 06:54:08 2003 +0000
     7.4 @@ -0,0 +1,64 @@
     7.5 +/*
     7.6 + * tumble: build a PDF file from image files
     7.7 + *
     7.8 + * $Id: tumble_input.h,v 1.1 2003/03/19 22:54:08 eric Exp $
     7.9 + * Copyright 2003 Eric Smith <eric@brouhaha.com>
    7.10 + *
    7.11 + * This program is free software; you can redistribute it and/or modify
    7.12 + * it under the terms of the GNU General Public License version 2 as
    7.13 + * published by the Free Software Foundation.  Note that permission is
    7.14 + * not granted to redistribute this program under the terms of any
    7.15 + * other version of the General Public License.
    7.16 + *
    7.17 + * This program is distributed in the hope that it will be useful,
    7.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.20 + * GNU General Public License for more details.
    7.21 + *
    7.22 + * You should have received a copy of the GNU General Public License
    7.23 + * along with this program; if not, write to the Free Software
    7.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    7.25 + */
    7.26 +
    7.27 +
    7.28 +typedef struct
    7.29 +{
    7.30 +  bool color;
    7.31 +  uint32_t width_samples, height_samples;
    7.32 +  double width_points, height_points;
    7.33 +  double x_resolution, y_resolution;
    7.34 +} image_info_t;
    7.35 +
    7.36 +
    7.37 +typedef struct
    7.38 +{
    7.39 +  bool (*open_input_file) (FILE *f, char *name);
    7.40 +  bool (*close_input_file) (void);
    7.41 +  bool (*last_input_page) (void);
    7.42 +  bool (*get_image_info) (int image,
    7.43 +			 input_attributes_t input_attributes,
    7.44 +			 image_info_t *image_info);
    7.45 +  bool (*process_image) (int image,
    7.46 +			 input_attributes_t input_attributes,
    7.47 +			 image_info_t *image_info,
    7.48 +			 pdf_page_handle page);
    7.49 +} input_handler_t;
    7.50 +
    7.51 +
    7.52 +void install_input_handler (input_handler_t *handler);
    7.53 +
    7.54 +
    7.55 +bool open_input_file (char *name);
    7.56 +bool close_input_file (void);
    7.57 +bool last_input_page (void);
    7.58 +bool get_image_info (int image,
    7.59 +		     input_attributes_t input_attributes,
    7.60 +		     image_info_t *image_info);
    7.61 +bool process_image (int image,
    7.62 +		    input_attributes_t input_attributes,
    7.63 +		    image_info_t *image_info,
    7.64 +		    pdf_page_handle page);
    7.65 +
    7.66 +
    7.67 +void init_tiff_handler (void);
    7.68 +void init_jpeg_handler (void);
     8.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble_jpeg.c
     8.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 +++ b/tumble_jpeg.c	Thu Mar 20 06:54:08 2003 +0000
     8.4 @@ -0,0 +1,176 @@
     8.5 +/*
     8.6 + * tumble: build a PDF file from image files
     8.7 + *
     8.8 + * $Id: tumble_jpeg.c,v 1.1 2003/03/19 22:54:08 eric Exp $
     8.9 + * Copyright 2003 Eric Smith <eric@brouhaha.com>
    8.10 + *
    8.11 + * This program is free software; you can redistribute it and/or modify
    8.12 + * it under the terms of the GNU General Public License version 2 as
    8.13 + * published by the Free Software Foundation.  Note that permission is
    8.14 + * not granted to redistribute this program under the terms of any
    8.15 + * other version of the General Public License.
    8.16 + *
    8.17 + * This program is distributed in the hope that it will be useful,
    8.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.20 + * GNU General Public License for more details.
    8.21 + *
    8.22 + * You should have received a copy of the GNU General Public License
    8.23 + * along with this program; if not, write to the Free Software
    8.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    8.25 + */
    8.26 +
    8.27 +
    8.28 +#include <stdbool.h>
    8.29 +#include <stdint.h>
    8.30 +#include <stdio.h>
    8.31 +#include <jpeglib.h>
    8.32 +
    8.33 +
    8.34 +#include "semantics.h"
    8.35 +#include "tumble.h"
    8.36 +#include "bitblt.h"
    8.37 +#include "pdf.h"
    8.38 +#include "tumble_input.h"
    8.39 +
    8.40 +
    8.41 +static FILE *jpeg_f;
    8.42 +
    8.43 +static struct jpeg_decompress_struct cinfo;
    8.44 +static struct jpeg_error_mgr jerr;
    8.45 +
    8.46 +
    8.47 +bool close_jpeg_input_file (void)
    8.48 +{
    8.49 +  return (1);
    8.50 +}
    8.51 +
    8.52 +
    8.53 +bool open_jpeg_input_file (FILE *f, char *name)
    8.54 +{
    8.55 +  uint8_t buf [2];
    8.56 +  size_t l;
    8.57 +
    8.58 +  l = fread (& buf [0], 1, sizeof (buf), f);
    8.59 +  if (l != sizeof (buf))
    8.60 +    return (0);
    8.61 +
    8.62 +  rewind (f);
    8.63 +
    8.64 +  if ((buf [0] != 0xff) || (buf [1] != 0xd8))
    8.65 +    return (0);
    8.66 +
    8.67 +  cinfo.err = jpeg_std_error (& jerr);
    8.68 +  jpeg_create_decompress (& cinfo);
    8.69 +
    8.70 +  jpeg_stdio_src (& cinfo, f);
    8.71 +
    8.72 +  jpeg_read_header (& cinfo, TRUE);
    8.73 +
    8.74 +  rewind (f);
    8.75 +
    8.76 +  jpeg_f = f;
    8.77 +
    8.78 +  return (1);
    8.79 +}
    8.80 +
    8.81 +
    8.82 +bool last_jpeg_input_page (void)
    8.83 +{
    8.84 +  return (1);
    8.85 +}
    8.86 +
    8.87 +
    8.88 +bool get_jpeg_image_info (int image,
    8.89 +			  input_attributes_t input_attributes,
    8.90 +			  image_info_t *image_info)
    8.91 +{
    8.92 +  double unit;
    8.93 +
    8.94 +  switch (cinfo.jpeg_color_space)
    8.95 +    {
    8.96 +    case JCS_GRAYSCALE:
    8.97 +      if (cinfo.num_components != 1)
    8.98 +	{
    8.99 +	  fprintf (stderr, "JPEG grayscale image has %d components, should have 1\n",
   8.100 +		   cinfo.num_components);
   8.101 +	  return (0);
   8.102 +	}
   8.103 +      image_info->color = 0;
   8.104 +      break;
   8.105 +    case JCS_RGB:
   8.106 +    case JCS_YCbCr:
   8.107 +      if (cinfo.num_components != 3)
   8.108 +	{
   8.109 +	  fprintf (stderr, "JPEG RGB or YCbCr image has %d components, should have 3\n",
   8.110 +		   cinfo.num_components);
   8.111 +	  return (0);
   8.112 +	}
   8.113 +      image_info->color = 1;
   8.114 +      break;
   8.115 +    default:
   8.116 +      fprintf (stderr, "JPEG color space %d not supported\n", cinfo.jpeg_color_space);
   8.117 +      return (0);
   8.118 +    }
   8.119 +  image_info->width_samples = cinfo.image_width;
   8.120 +  image_info->height_samples = cinfo.image_height;
   8.121 +
   8.122 +  if (cinfo.saw_JFIF_marker & cinfo.density_unit)
   8.123 +    {
   8.124 +      switch (cinfo.density_unit)
   8.125 +	{
   8.126 +	case 1:  /* samples per inch */
   8.127 +	  unit = 1.0;
   8.128 +	  break;
   8.129 +	case 2:  /* samples per cm */
   8.130 +	  unit = 2.54;
   8.131 +	  break;
   8.132 +	default:
   8.133 +	  fprintf (stderr, "JFIF density unit %d not supported\n", cinfo.density_unit);
   8.134 +	  return (0);
   8.135 +	}
   8.136 +      image_info->width_points = ((image_info->width_samples * POINTS_PER_INCH) /
   8.137 +				  (cinfo.X_density * unit));
   8.138 +      image_info->height_points = ((image_info->height_samples * POINTS_PER_INCH) /
   8.139 +				   (cinfo.Y_density * unit));
   8.140 +    }
   8.141 +  else
   8.142 +    {
   8.143 +      /* assume 300 DPI - not great, but what else can we do? */
   8.144 +      image_info->width_points = (image_info->width_samples * POINTS_PER_INCH) / 300.0;
   8.145 +      image_info->height_points = (image_info->height_samples * POINTS_PER_INCH) / 300.0;
   8.146 +    }
   8.147 +
   8.148 +  return (1);
   8.149 +}
   8.150 +
   8.151 +
   8.152 +bool process_jpeg_image (int image,  /* range 1 .. n */
   8.153 +			 input_attributes_t input_attributes,
   8.154 +			 image_info_t *image_info,
   8.155 +			 pdf_page_handle page)
   8.156 +{
   8.157 +  pdf_write_jpeg_image (page,
   8.158 +			0, 0,  /* x, y */
   8.159 +			image_info->width_points,
   8.160 +			image_info->height_points,
   8.161 +			jpeg_f);
   8.162 +
   8.163 +  return (page);
   8.164 +}
   8.165 +
   8.166 +
   8.167 +input_handler_t jpeg_handler =
   8.168 +  {
   8.169 +    open_jpeg_input_file,
   8.170 +    close_jpeg_input_file,
   8.171 +    last_jpeg_input_page,
   8.172 +    get_jpeg_image_info,
   8.173 +    process_jpeg_image
   8.174 +  };
   8.175 +
   8.176 +
   8.177 +void init_jpeg_handler (void)
   8.178 +{
   8.179 +  install_input_handler (& jpeg_handler);
   8.180 +}
     9.1 diff -r 3fe049d83e22 -r 752599b50ff3 tumble_tiff.c
     9.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 +++ b/tumble_tiff.c	Thu Mar 20 06:54:08 2003 +0000
     9.4 @@ -0,0 +1,351 @@
     9.5 +/*
     9.6 + * tumble: build a PDF file from image files
     9.7 + *
     9.8 + * $Id: tumble_tiff.c,v 1.1 2003/03/19 22:54:08 eric Exp $
     9.9 + * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
    9.10 + *
    9.11 + * This program is free software; you can redistribute it and/or modify
    9.12 + * it under the terms of the GNU General Public License version 2 as
    9.13 + * published by the Free Software Foundation.  Note that permission is
    9.14 + * not granted to redistribute this program under the terms of any
    9.15 + * other version of the General Public License.
    9.16 + *
    9.17 + * This program is distributed in the hope that it will be useful,
    9.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.20 + * GNU General Public License for more details.
    9.21 + *
    9.22 + * You should have received a copy of the GNU General Public License
    9.23 + * along with this program; if not, write to the Free Software
    9.24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    9.25 + */
    9.26 +
    9.27 +
    9.28 +#include <stdbool.h>
    9.29 +#include <stdint.h>
    9.30 +#include <stdio.h>
    9.31 +#include <stdlib.h>
    9.32 +#include <string.h>
    9.33 +
    9.34 +#include <tiffio.h>
    9.35 +#define TIFF_REVERSE_BITS
    9.36 +
    9.37 +
    9.38 +#include "semantics.h"
    9.39 +#include "tumble.h"
    9.40 +#include "bitblt.h"
    9.41 +#include "pdf.h"
    9.42 +#include "tumble_input.h"
    9.43 +
    9.44 +
    9.45 +TIFF *tiff_in;
    9.46 +
    9.47 +
    9.48 +#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
    9.49 +
    9.50 +
    9.51 +bool close_tiff_input_file (void)
    9.52 +{
    9.53 +  TIFFClose (tiff_in);
    9.54 +  return (1);
    9.55 +}
    9.56 +
    9.57 +
    9.58 +bool open_tiff_input_file (FILE *f, char *name)
    9.59 +{
    9.60 +  uint8_t buf [2];
    9.61 +  size_t l;
    9.62 +
    9.63 +  l = fread (& buf [0], 1, sizeof (buf), f);
    9.64 +  if (l != sizeof (buf))
    9.65 +    return (0);
    9.66 +
    9.67 +  rewind (f);
    9.68 +
    9.69 +  if ((buf [0] != 0x49) || (buf [1] != 0x49))
    9.70 +    return (0);
    9.71 +
    9.72 +  /* $$$ should we dup the file descriptor here, so that later closing f
    9.73 +     won't cause problems? */
    9.74 +  tiff_in = TIFFFdOpen (fileno (f), name, "r");
    9.75 +  if (! tiff_in)
    9.76 +    {
    9.77 +      fprintf (stderr, "can't open input file '%s'\n", name);
    9.78 +      return (0);
    9.79 +    }
    9.80 +  return (1);
    9.81 +}
    9.82 +
    9.83 +
    9.84 +bool last_tiff_input_page (void)
    9.85 +{
    9.86 +  return (TIFFLastDirectory (tiff_in));
    9.87 +}
    9.88 +
    9.89 +
    9.90 +bool get_tiff_image_info (int image,
    9.91 +			  input_attributes_t input_attributes,
    9.92 +			  image_info_t *image_info)
    9.93 +{
    9.94 +  uint32_t image_height, image_width;
    9.95 +  uint16_t samples_per_pixel;
    9.96 +  uint16_t bits_per_sample;
    9.97 +  uint16_t planar_config;
    9.98 +
    9.99 +  uint16_t resolution_unit;
   9.100 +  float x_resolution, y_resolution;
   9.101 +
   9.102 +  double dest_x_resolution, dest_y_resolution;
   9.103 +
   9.104 +#ifdef CHECK_DEPTH
   9.105 +  uint32_t image_depth;
   9.106 +#endif
   9.107 +
   9.108 +  if (! TIFFSetDirectory (tiff_in, image - 1))
   9.109 +    {
   9.110 +      fprintf (stderr, "can't find page %d of input file\n", image);
   9.111 +      return (0);
   9.112 +    }
   9.113 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
   9.114 +    {
   9.115 +      fprintf (stderr, "can't get image height\n");
   9.116 +      return (0);
   9.117 +    }
   9.118 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
   9.119 +    {
   9.120 +      fprintf (stderr, "can't get image width\n");
   9.121 +      return (0);
   9.122 +    }
   9.123 +
   9.124 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
   9.125 +    {
   9.126 +      fprintf (stderr, "can't get samples per pixel\n");
   9.127 +      return (0);
   9.128 +    }
   9.129 +
   9.130 +#ifdef CHECK_DEPTH
   9.131 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
   9.132 +    {
   9.133 +      fprintf (stderr, "can't get image depth\n");
   9.134 +      return (0);
   9.135 +    }
   9.136 +#endif
   9.137 +
   9.138 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
   9.139 +    {
   9.140 +      fprintf (stderr, "can't get bits per sample\n");
   9.141 +      return (0);
   9.142 +    }
   9.143 +
   9.144 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
   9.145 +    planar_config = 1;
   9.146 +
   9.147 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
   9.148 +    resolution_unit = 2;
   9.149 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
   9.150 +    x_resolution = 300;
   9.151 +  if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
   9.152 +    y_resolution = 300;
   9.153 +
   9.154 +  if (samples_per_pixel != 1)
   9.155 +    {
   9.156 +      fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
   9.157 +      return (0);
   9.158 +    }
   9.159 +
   9.160 +#ifdef CHECK_DEPTH
   9.161 +  if (image_depth != 1)
   9.162 +    {
   9.163 +      fprintf (stderr, "image depth %u, must be 1\n", image_depth);
   9.164 +      return (0);
   9.165 +    }
   9.166 +#endif
   9.167 +
   9.168 +  if (bits_per_sample != 1)
   9.169 +    {
   9.170 +      fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
   9.171 +      return (0);
   9.172 +    }
   9.173 +
   9.174 +  if (planar_config != 1)
   9.175 +    {
   9.176 +      fprintf (stderr, "planar config %u, must be 1\n", planar_config);
   9.177 +      return (0);
   9.178 +    }
   9.179 +
   9.180 +  if (input_attributes.has_resolution)
   9.181 +    {
   9.182 +      x_resolution = input_attributes.x_resolution;
   9.183 +      y_resolution = input_attributes.y_resolution;
   9.184 +    }
   9.185 +
   9.186 +  if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   9.187 +    {
   9.188 +      image_info->width_samples  = image_height;
   9.189 +      image_info->height_samples = image_width;
   9.190 +      dest_x_resolution = y_resolution;
   9.191 +      dest_y_resolution = x_resolution;
   9.192 +      SWAP (double, image_info->width_points, image_info->height_points);
   9.193 +    }
   9.194 +  else
   9.195 +    {
   9.196 +      image_info->width_samples = image_width;
   9.197 +      image_info->height_samples = image_height;
   9.198 +      dest_x_resolution = x_resolution;
   9.199 +      dest_y_resolution = y_resolution;
   9.200 +    }
   9.201 +
   9.202 +  image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
   9.203 +  image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
   9.204 +
   9.205 +  if ((image_info->height_points > PAGE_MAX_POINTS) || 
   9.206 +      (image_info->width_points > PAGE_MAX_POINTS))
   9.207 +    {
   9.208 +      fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
   9.209 +      return (0);
   9.210 +    }
   9.211 +
   9.212 +  return (1);
   9.213 +}
   9.214 +
   9.215 +
   9.216 +/* frees original! */
   9.217 +static Bitmap *resize_bitmap (Bitmap *src,
   9.218 +			      double x_resolution,
   9.219 +			      double y_resolution,
   9.220 +			      input_attributes_t input_attributes)
   9.221 +{
   9.222 +  Rect src_rect;
   9.223 +  Point dest_min;
   9.224 +  Bitmap *dest;
   9.225 +
   9.226 +  int width_pixels = input_attributes.page_size.width * x_resolution;
   9.227 +  int height_pixels = input_attributes.page_size.height * y_resolution;
   9.228 +
   9.229 +  src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
   9.230 +  src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
   9.231 +  src_rect.max.x = src_rect.min.x + width_pixels;
   9.232 +  src_rect.max.y = src_rect.min.y + height_pixels;
   9.233 +
   9.234 +  dest_min.x = 0;
   9.235 +  dest_min.y = 0;
   9.236 +
   9.237 +  dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
   9.238 +  free_bitmap (src);
   9.239 +  return (dest);
   9.240 +}
   9.241 +
   9.242 +
   9.243 +/* "in place" rotation */
   9.244 +static void rotate_bitmap (Bitmap *src,
   9.245 +			   input_attributes_t input_attributes)
   9.246 +{
   9.247 +  switch (input_attributes.rotation)
   9.248 +    {
   9.249 +    case 0: break;
   9.250 +    case 90: rot_90 (src); break;
   9.251 +    case 180: rot_180 (src); break;
   9.252 +    case 270: rot_270 (src); break;
   9.253 +    default:
   9.254 +      fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
   9.255 +    }
   9.256 +}
   9.257 +
   9.258 +
   9.259 +bool process_tiff_image (int image,  /* range 1 .. n */
   9.260 +			 input_attributes_t input_attributes,
   9.261 +			 image_info_t *image_info,
   9.262 +			 pdf_page_handle page)
   9.263 +{
   9.264 +  Rect rect;
   9.265 +  Bitmap *bitmap = NULL;
   9.266 +
   9.267 +  int row;
   9.268 +
   9.269 +  rect.min.x = 0;
   9.270 +  rect.min.y = 0;
   9.271 +
   9.272 +  if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   9.273 +    {
   9.274 +      rect.max.x = image_info->height_samples;
   9.275 +      rect.max.y = image_info->width_samples;
   9.276 +    }
   9.277 +  else
   9.278 +    {
   9.279 +      rect.max.x = image_info->width_samples;
   9.280 +      rect.max.y = image_info->height_samples;
   9.281 +    }
   9.282 +
   9.283 +  bitmap = create_bitmap (& rect);
   9.284 +
   9.285 +  if (! bitmap)
   9.286 +    {
   9.287 +      fprintf (stderr, "can't allocate bitmap\n");
   9.288 +      fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
   9.289 +      goto fail;
   9.290 +    }
   9.291 +
   9.292 +  for (row = 0; row < rect.max.y; row++)
   9.293 +    if (1 != TIFFReadScanline (tiff_in,
   9.294 +			       bitmap->bits + row * bitmap->row_words,
   9.295 +			       row,
   9.296 +			       0))
   9.297 +      {
   9.298 +	fprintf (stderr, "can't read TIFF scanline\n");
   9.299 +	goto fail;
   9.300 +      }
   9.301 +
   9.302 +#ifdef TIFF_REVERSE_BITS
   9.303 +  reverse_bits ((uint8_t *) bitmap->bits,
   9.304 +		rect.max.y * bitmap->row_words * sizeof (word_t));
   9.305 +#endif /* TIFF_REVERSE_BITS */
   9.306 +
   9.307 +#if 0
   9.308 +  if (input_attributes.has_page_size)
   9.309 +    bitmap = resize_bitmap (bitmap,
   9.310 +			    x_resolution,
   9.311 +			    y_resolution,
   9.312 +			    input_attributes);
   9.313 +#endif
   9.314 +
   9.315 +  rotate_bitmap (bitmap,
   9.316 +		 input_attributes);
   9.317 +
   9.318 +#if 0
   9.319 +  pdf_write_text (page);
   9.320 +#else
   9.321 +  pdf_write_g4_fax_image (page,
   9.322 +			  0, 0,  /* x, y */
   9.323 +			  image_info->width_points, image_info->height_points,
   9.324 +			  bitmap,
   9.325 +			  0, /* ImageMask */
   9.326 +			  0, 0, 0,  /* r, g, b */
   9.327 +			  0); /* BlackIs1 */
   9.328 +#endif
   9.329 +
   9.330 +  if (bitmap)
   9.331 +    free_bitmap (bitmap);
   9.332 +  return (page);
   9.333 +
   9.334 + fail:
   9.335 +  if (bitmap)
   9.336 +    free_bitmap (bitmap);
   9.337 +
   9.338 +  return (NULL);
   9.339 +}
   9.340 +
   9.341 +
   9.342 +input_handler_t tiff_handler =
   9.343 +  {
   9.344 +    open_tiff_input_file,
   9.345 +    close_tiff_input_file,
   9.346 +    last_tiff_input_page,
   9.347 +    get_tiff_image_info,
   9.348 +    process_tiff_image
   9.349 +  };
   9.350 +
   9.351 +
   9.352 +void init_tiff_handler (void)
   9.353 +{
   9.354 +  install_input_handler (& tiff_handler);
   9.355 +}