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