t2p.c

Thu, 13 Mar 2003 07:59:10 +0000

author
eric
date
Thu, 13 Mar 2003 07:59:10 +0000
changeset 121
e50c7f76f2f6
parent 116
73d3ba4f6ba2
permissions
-rw-r--r--

don't use page mode USE_OUTLINES if there are no outline entries.

eric@10 1 /*
eric@44 2 * t2p: Create a PDF file from the contents of one or more TIFF
eric@44 3 * bilevel image files. The images in the resulting PDF file
eric@44 4 * will be compressed using ITU-T T.6 (G4) fax encoding.
eric@29 5 *
eric@10 6 * Main program
eric@121 7 * $Id: t2p.c,v 1.31 2003/03/12 23:59:10 eric Exp $
eric@49 8 * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
eric@10 9 *
eric@10 10 * This program is free software; you can redistribute it and/or modify
eric@10 11 * it under the terms of the GNU General Public License version 2 as
eric@10 12 * published by the Free Software Foundation. Note that permission is
eric@10 13 * not granted to redistribute this program under the terms of any
eric@10 14 * other version of the General Public License.
eric@10 15 *
eric@10 16 * This program is distributed in the hope that it will be useful,
eric@10 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
eric@10 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
eric@10 19 * GNU General Public License for more details.
eric@10 20 *
eric@10 21 * You should have received a copy of the GNU General Public License
eric@10 22 * along with this program; if not, write to the Free Software
eric@62 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
eric@62 24 */
eric@10 25
eric@10 26
eric@49 27 #include <stdarg.h>
eric@48 28 #include <stdbool.h>
eric@48 29 #include <stdint.h>
eric@10 30 #include <stdio.h>
eric@28 31 #include <stdlib.h>
eric@62 32 #include <string.h>
eric@28 33 #include <unistd.h>
eric@47 34
eric@10 35 #include <tiffio.h>
eric@47 36 #define TIFF_REVERSE_BITS
eric@47 37
eric@10 38 #include "bitblt.h"
eric@18 39 #include "semantics.h"
eric@10 40 #include "parser.tab.h"
eric@44 41 #include "t2p.h"
eric@62 42 #include "pdf.h"
eric@10 43
eric@10 44
eric@49 45 #define MAX_INPUT_FILES 5000
eric@49 46
eric@28 47 #define POINTS_PER_INCH 72
eric@28 48
eric@28 49 /* page size limited by Acrobat Reader to 45 inches on a side */
eric@28 50 #define PAGE_MAX_INCHES 45
eric@28 51 #define PAGE_MAX_POINTS (PAGE_MAX_INCHES * POINTS_PER_INCH)
eric@28 52
eric@28 53
eric@26 54 typedef struct output_file_t
eric@26 55 {
eric@26 56 struct output_file_t *next;
eric@26 57 char *name;
eric@62 58 pdf_file_handle pdf;
eric@26 59 } output_file_t;
eric@26 60
eric@26 61
eric@49 62 int verbose;
eric@49 63
eric@49 64
eric@26 65 char *in_filename;
eric@10 66 TIFF *in;
eric@26 67 output_file_t *output_files;
eric@26 68 output_file_t *out;
eric@10 69
eric@10 70
eric@49 71 char *progname;
eric@49 72
eric@49 73
eric@49 74 bool close_tiff_input_file (void);
eric@49 75 bool close_pdf_output_files (void);
eric@49 76
eric@49 77
eric@49 78 void usage (void)
eric@49 79 {
eric@50 80 fprintf (stderr, "\n");
eric@50 81 fprintf (stderr, "t2p - Copyright 2001-2003 Eric Smith <eric@brouhaha.com>\n");
eric@50 82 fprintf (stderr, "http://www.brouhaha.com/~eric/software/t2p/\n");
eric@50 83 fprintf (stderr, "\n");
eric@49 84 fprintf (stderr, "usage:\n");
eric@49 85 fprintf (stderr, " %s [options] -s spec\n", progname);
eric@49 86 fprintf (stderr, " %s [options] <input.tif>... -o <output.pdf>\n", progname);
eric@49 87 fprintf (stderr, "options:\n");
eric@49 88 fprintf (stderr, " -v verbose\n");
eric@62 89 fprintf (stderr, " -b fmt create bookmarks\n");
eric@62 90 fprintf (stderr, "bookmark format:\n");
eric@74 91 fprintf (stderr, " %%F file name (sans suffix)\n");
eric@62 92 fprintf (stderr, " %%p page number\n");
eric@49 93 }
eric@49 94
eric@49 95
eric@49 96 /* generate fatal error message to stderr, doesn't return */
eric@49 97 void fatal (int ret, char *format, ...)
eric@49 98 {
eric@49 99 va_list ap;
eric@49 100
eric@49 101 fprintf (stderr, "fatal error");
eric@49 102 if (format)
eric@49 103 {
eric@49 104 fprintf (stderr, ": ");
eric@49 105 va_start (ap, format);
eric@49 106 vfprintf (stderr, format, ap);
eric@49 107 va_end (ap);
eric@49 108 }
eric@49 109 else
eric@49 110 fprintf (stderr, "\n");
eric@49 111 if (ret == 1)
eric@49 112 usage ();
eric@49 113 close_tiff_input_file ();
eric@49 114 close_pdf_output_files ();
eric@49 115 exit (ret);
eric@49 116 }
eric@49 117
eric@49 118
eric@48 119 bool close_tiff_input_file (void)
eric@10 120 {
eric@10 121 if (in)
eric@26 122 {
eric@26 123 free (in_filename);
eric@26 124 TIFFClose (in);
eric@26 125 }
eric@10 126 in = NULL;
eric@26 127 in_filename = NULL;
eric@10 128 return (1);
eric@10 129 }
eric@10 130
eric@49 131
eric@48 132 bool open_tiff_input_file (char *name)
eric@10 133 {
eric@10 134 if (in)
eric@26 135 {
eric@26 136 if (strcmp (name, in_filename) == 0)
eric@26 137 return (1);
eric@26 138 close_tiff_input_file ();
eric@26 139 }
eric@26 140 in_filename = strdup (name);
eric@26 141 if (! in_filename)
eric@26 142 {
eric@26 143 fprintf (stderr, "can't strdup input filename '%s'\n", name);
eric@26 144 return (0);
eric@26 145 }
eric@10 146 in = TIFFOpen (name, "r");
eric@10 147 if (! in)
eric@10 148 {
eric@10 149 fprintf (stderr, "can't open input file '%s'\n", name);
eric@26 150 free (in_filename);
eric@10 151 return (0);
eric@10 152 }
eric@10 153 return (1);
eric@10 154 }
eric@10 155
eric@10 156
eric@48 157 bool close_pdf_output_files (void)
eric@10 158 {
eric@26 159 output_file_t *o, *n;
eric@26 160
eric@26 161 for (o = output_files; o; o = n)
eric@26 162 {
eric@26 163 n = o->next;
eric@62 164 pdf_close (o->pdf);
eric@26 165 free (o->name);
eric@26 166 free (o);
eric@26 167 }
eric@10 168 out = NULL;
eric@26 169 output_files = NULL;
eric@10 170 return (1);
eric@10 171 }
eric@10 172
eric@48 173 bool open_pdf_output_file (char *name,
eric@48 174 pdf_file_attributes_t *attributes)
eric@10 175 {
eric@26 176 output_file_t *o;
eric@26 177
eric@26 178 if (out && (strcmp (name, out->name) == 0))
eric@26 179 return (1);
eric@26 180 for (o = output_files; o; o = o->next)
eric@26 181 if (strcmp (name, o->name) == 0)
eric@26 182 {
eric@26 183 out = o;
eric@26 184 return (1);
eric@26 185 }
eric@26 186 o = calloc (1, sizeof (output_file_t));
eric@29 187 if (! o)
eric@10 188 {
eric@26 189 fprintf (stderr, "can't calloc output file struct for '%s'\n", name);
eric@26 190 return (0);
eric@26 191 }
eric@26 192
eric@26 193 o->name = strdup (name);
eric@26 194 if (! o->name)
eric@26 195 {
eric@26 196 fprintf (stderr, "can't strdup output filename '%s'\n", name);
eric@26 197 free (o);
eric@10 198 return (0);
eric@10 199 }
eric@26 200
eric@121 201 o->pdf = pdf_create (name, (attributes->has_bookmarks ?
eric@121 202 PDF_PAGE_MODE_USE_OUTLINES :
eric@121 203 PDF_PAGE_MODE_USE_NONE));
eric@26 204 if (! o->pdf)
eric@26 205 {
eric@26 206 fprintf (stderr, "can't open output file '%s'\n", name);
eric@26 207 free (o->name);
eric@26 208 free (o);
eric@26 209 return (0);
eric@26 210 }
eric@26 211
eric@30 212 if (attributes->author)
eric@62 213 pdf_set_author (o->pdf, attributes->author);
eric@30 214 if (attributes->creator)
eric@62 215 pdf_set_creator (o->pdf, attributes->creator);
eric@30 216 if (attributes->title)
eric@62 217 pdf_set_title (o->pdf, attributes->title);
eric@30 218 if (attributes->subject)
eric@62 219 pdf_set_subject (o->pdf, attributes->subject);
eric@30 220 if (attributes->keywords)
eric@62 221 pdf_set_keywords (o->pdf, attributes->keywords);
eric@30 222
eric@26 223 /* prepend new output file onto list */
eric@26 224 o->next = output_files;
eric@26 225 output_files = o;
eric@26 226
eric@26 227 out = o;
eric@10 228 return (1);
eric@10 229 }
eric@10 230
eric@10 231
eric@25 232 void process_page_numbers (int page_index,
eric@25 233 int count,
eric@25 234 int base,
eric@25 235 page_label_t *page_label)
eric@25 236 {
eric@25 237 }
eric@25 238
eric@25 239
eric@42 240 /* frees original! */
eric@42 241 static Bitmap *resize_bitmap (Bitmap *src,
eric@92 242 double x_resolution,
eric@92 243 double y_resolution,
eric@36 244 input_attributes_t input_attributes)
eric@32 245 {
eric@32 246 Rect src_rect;
eric@42 247 Point dest_min;
eric@42 248 Bitmap *dest;
eric@32 249
eric@42 250 int width_pixels = input_attributes.page_size.width * x_resolution;
eric@42 251 int height_pixels = input_attributes.page_size.height * y_resolution;
eric@42 252
eric@42 253 src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
eric@42 254 src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
eric@42 255 src_rect.max.x = src_rect.min.x + width_pixels;
eric@42 256 src_rect.max.y = src_rect.min.y + height_pixels;
eric@36 257
eric@42 258 dest_min.x = 0;
eric@42 259 dest_min.y = 0;
eric@32 260
eric@43 261 dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
eric@42 262 free_bitmap (src);
eric@42 263 return (dest);
eric@42 264 }
eric@32 265
eric@42 266
eric@42 267 /* "in place" rotation */
eric@42 268 static void rotate_bitmap (Bitmap *src,
eric@42 269 input_attributes_t input_attributes)
eric@42 270 {
eric@36 271 switch (input_attributes.rotation)
eric@32 272 {
eric@42 273 case 0: break;
eric@42 274 case 90: rot_90 (src); break;
eric@42 275 case 180: rot_180 (src); break;
eric@42 276 case 270: rot_270 (src); break;
eric@32 277 default:
eric@32 278 fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
eric@32 279 }
eric@32 280 }
eric@32 281
eric@32 282
eric@32 283 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
eric@32 284
eric@49 285
eric@49 286 bool last_tiff_page (void)
eric@49 287 {
eric@49 288 return (TIFFLastDirectory (in));
eric@49 289 }
eric@49 290
eric@49 291
eric@108 292 bool process_tiff_page (int image, /* range 1 .. n */
eric@108 293 input_attributes_t input_attributes,
eric@108 294 bookmark_t *bookmarks)
eric@10 295 {
eric@29 296 int result = 0;
eric@29 297
eric@48 298 uint32_t image_length, image_width;
eric@48 299 uint32_t dest_image_length, dest_image_width;
eric@10 300 #ifdef CHECK_DEPTH
eric@48 301 uint32_t image_depth;
eric@10 302 #endif
eric@29 303
eric@48 304 uint16_t samples_per_pixel;
eric@48 305 uint16_t bits_per_sample;
eric@48 306 uint16_t planar_config;
eric@32 307
eric@48 308 uint16_t resolution_unit;
eric@94 309 float x_resolution, y_resolution;
eric@92 310 double dest_x_resolution, dest_y_resolution;
eric@32 311
eric@62 312 double width_points, height_points; /* really 1/72 inch units rather than
eric@62 313 points */
eric@28 314
eric@42 315 Rect rect;
eric@74 316 Bitmap *bitmap = NULL;
eric@42 317
eric@32 318 int row;
eric@10 319
eric@62 320 pdf_page_handle page;
eric@28 321
eric@10 322 if (! TIFFSetDirectory (in, image - 1))
eric@10 323 {
eric@10 324 fprintf (stderr, "can't find page %d of input file\n", image);
eric@10 325 goto fail;
eric@10 326 }
eric@10 327 if (1 != TIFFGetField (in, TIFFTAG_IMAGELENGTH, & image_length))
eric@10 328 {
eric@10 329 fprintf (stderr, "can't get image length\n");
eric@10 330 goto fail;
eric@10 331 }
eric@10 332 if (1 != TIFFGetField (in, TIFFTAG_IMAGEWIDTH, & image_width))
eric@10 333 {
eric@10 334 fprintf (stderr, "can't get image width\n");
eric@10 335 goto fail;
eric@10 336 }
eric@29 337
eric@29 338 if (1 != TIFFGetField (in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
eric@29 339 {
eric@29 340 fprintf (stderr, "can't get samples per pixel\n");
eric@29 341 goto fail;
eric@29 342 }
eric@29 343
eric@10 344 #ifdef CHECK_DEPTH
eric@10 345 if (1 != TIFFGetField (in, TIFFTAG_IMAGEDEPTH, & image_depth))
eric@10 346 {
eric@10 347 fprintf (stderr, "can't get image depth\n");
eric@10 348 goto fail;
eric@10 349 }
eric@10 350 #endif
eric@10 351
eric@10 352 if (1 != TIFFGetField (in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
eric@10 353 {
eric@10 354 fprintf (stderr, "can't get bits per sample\n");
eric@10 355 goto fail;
eric@10 356 }
eric@10 357
eric@10 358 if (1 != TIFFGetField (in, TIFFTAG_PLANARCONFIG, & planar_config))
eric@10 359 planar_config = 1;
eric@10 360
eric@10 361 if (1 != TIFFGetField (in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
eric@10 362 resolution_unit = 2;
eric@10 363 if (1 != TIFFGetField (in, TIFFTAG_XRESOLUTION, & x_resolution))
eric@10 364 x_resolution = 300;
eric@10 365 if (1 != TIFFGetField (in, TIFFTAG_YRESOLUTION, & y_resolution))
eric@10 366 y_resolution = 300;
eric@10 367
eric@29 368 if (samples_per_pixel != 1)
eric@29 369 {
eric@29 370 fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
eric@29 371 goto fail;
eric@29 372 }
eric@29 373
eric@10 374 #ifdef CHECK_DEPTH
eric@10 375 if (image_depth != 1)
eric@10 376 {
eric@10 377 fprintf (stderr, "image depth %u, must be 1\n", image_depth);
eric@10 378 goto fail;
eric@10 379 }
eric@10 380 #endif
eric@10 381
eric@10 382 if (bits_per_sample != 1)
eric@10 383 {
eric@10 384 fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
eric@10 385 goto fail;
eric@10 386 }
eric@10 387
eric@10 388 if (planar_config != 1)
eric@10 389 {
eric@10 390 fprintf (stderr, "planar config %u, must be 1\n", planar_config);
eric@10 391 goto fail;
eric@10 392 }
eric@10 393
eric@36 394 if (input_attributes.has_resolution)
eric@32 395 {
eric@36 396 x_resolution = input_attributes.x_resolution;
eric@36 397 y_resolution = input_attributes.y_resolution;
eric@32 398 }
eric@32 399
eric@32 400 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
eric@32 401 {
eric@32 402 dest_image_width = image_length;
eric@32 403 dest_image_length = image_width;
eric@32 404 dest_x_resolution = y_resolution;
eric@32 405 dest_y_resolution = x_resolution;
eric@62 406 SWAP (double, width_points, height_points); /* $$$ not yet set!!! */
eric@32 407 }
eric@32 408 else
eric@32 409 {
eric@32 410 dest_image_width = image_width;
eric@32 411 dest_image_length = image_length;
eric@32 412 dest_x_resolution = x_resolution;
eric@32 413 dest_y_resolution = y_resolution;
eric@32 414 }
eric@32 415
eric@42 416 rect.min.x = 0;
eric@42 417 rect.min.y = 0;
eric@42 418 rect.max.x = image_width;
eric@42 419 rect.max.y = image_length;
eric@42 420
eric@42 421 bitmap = create_bitmap (& rect);
eric@42 422
eric@42 423 if (! bitmap)
eric@10 424 {
eric@32 425 fprintf (stderr, "can't allocate bitmap\n");
eric@10 426 goto fail;
eric@10 427 }
eric@10 428
eric@10 429 for (row = 0; row < image_length; row++)
eric@32 430 if (1 != TIFFReadScanline (in,
eric@43 431 bitmap->bits + row * bitmap->row_words,
eric@32 432 row,
eric@32 433 0))
eric@32 434 {
eric@32 435 fprintf (stderr, "can't read TIFF scanline\n");
eric@32 436 goto fail;
eric@32 437 }
eric@28 438
eric@47 439 #ifdef TIFF_REVERSE_BITS
eric@48 440 reverse_bits ((uint8_t *) bitmap->bits,
eric@108 441 image_length * bitmap->row_words * sizeof (word_t));
eric@47 442 #endif /* TIFF_REVERSE_BITS */
eric@47 443
eric@94 444 #if 0
eric@46 445 if (input_attributes.has_page_size)
eric@46 446 bitmap = resize_bitmap (bitmap,
eric@46 447 x_resolution,
eric@46 448 y_resolution,
eric@46 449 input_attributes);
eric@94 450 #endif
eric@42 451
eric@42 452 rotate_bitmap (bitmap,
eric@42 453 input_attributes);
eric@28 454
eric@42 455 width_points = (rect_width (& bitmap->rect) / dest_x_resolution) * POINTS_PER_INCH;
eric@42 456 height_points = (rect_height (& bitmap->rect) / dest_y_resolution) * POINTS_PER_INCH;
eric@36 457
eric@36 458 if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS))
eric@36 459 {
eric@36 460 fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
eric@36 461 goto fail;
eric@36 462 }
eric@36 463
eric@62 464 page = pdf_new_page (out->pdf, width_points, height_points);
eric@28 465
eric@121 466 #if 0
eric@121 467 pdf_write_text (page);
eric@121 468 #else
eric@62 469 pdf_write_g4_fax_image (page,
eric@66 470 0, 0, /* x, y */
eric@66 471 width_points, height_points,
eric@62 472 bitmap,
eric@62 473 0, /* ImageMask */
eric@66 474 0, 0, 0, /* r, g, b */
eric@62 475 0); /* BlackIs1 */
eric@121 476 #endif
eric@62 477
eric@74 478 while (bookmarks)
eric@74 479 {
eric@74 480 /* $$$ need to handle level here */
eric@74 481 pdf_new_bookmark (NULL, bookmarks->name, 0, page);
eric@74 482 bookmarks = bookmarks->next;
eric@74 483 }
eric@28 484
eric@29 485 result = 1;
eric@10 486
eric@10 487 fail:
eric@74 488 if (bitmap)
eric@74 489 free_bitmap (bitmap);
eric@74 490
eric@29 491 return (result);
eric@10 492 }
eric@10 493
eric@10 494
eric@108 495 #if 0
eric@108 496 bool process_jpeg_page (int image, /* range 1 .. n */
eric@108 497 input_attributes_t input_attributes,
eric@108 498 bookmark_t *bookmarks)
eric@108 499 {
eric@108 500 int result = 0;
eric@108 501 FILE *f;
eric@108 502 pdf_page_handle page;
eric@108 503
eric@108 504 f = fopen (filename, "rb");
eric@108 505 if (! f)
eric@108 506 fatal ("error opening input file '%s'\n", filename);
eric@108 507
eric@108 508 page = pdf_new_page (out->pdf, width_points, height_points);
eric@108 509
eric@108 510 pdf_write_jpeg_image (page,
eric@108 511 0, 0, /* x, y */
eric@108 512 width_points, height_points,
eric@108 513 f);
eric@108 514
eric@108 515 return (result);
eric@108 516 }
eric@108 517 #endif
eric@108 518
eric@108 519
eric@108 520 bool process_page (int image, /* range 1 .. n */
eric@108 521 input_attributes_t input_attributes,
eric@108 522 bookmark_t *bookmarks)
eric@108 523 {
eric@108 524 int result = 0;
eric@108 525
eric@108 526 result = process_tiff_page (image, input_attributes, bookmarks);
eric@108 527
eric@108 528 return (result);
eric@108 529 }
eric@108 530
eric@108 531
eric@74 532 #define MAX_BOOKMARK_NAME_LEN 500
eric@74 533
eric@74 534
eric@74 535 static int filename_length_without_suffix (char *in_fn)
eric@74 536 {
eric@74 537 char *p;
eric@74 538 int len = strlen (in_fn);
eric@74 539
eric@74 540 p = strrchr (in_fn, '.');
eric@74 541 if (p && ((strcasecmp (p, ".tif") == 0) ||
eric@74 542 (strcasecmp (p, ".tiff") == 0)))
eric@74 543 return (p - in_fn);
eric@74 544 return (len);
eric@74 545 }
eric@74 546
eric@74 547
eric@74 548 /* $$$ this function should ensure that it doesn't overflow the name string! */
eric@74 549 static void generate_bookmark_name (char *name,
eric@74 550 char *bookmark_fmt,
eric@74 551 char *in_fn,
eric@74 552 int page)
eric@74 553 {
eric@74 554 bool meta = 0;
eric@74 555 int len;
eric@74 556
eric@74 557 while (*bookmark_fmt)
eric@74 558 {
eric@74 559 if (meta)
eric@74 560 {
eric@74 561 meta = 0;
eric@74 562 switch (*bookmark_fmt)
eric@74 563 {
eric@74 564 case '%':
eric@74 565 *(name++) = '%';
eric@74 566 break;
eric@74 567 case 'F':
eric@74 568 len = filename_length_without_suffix (in_fn);
eric@74 569 strncpy (name, in_fn, len);
eric@74 570 name += len;
eric@74 571 break;
eric@74 572 case 'p':
eric@74 573 sprintf (name, "%d", page);
eric@74 574 name += strlen (name);
eric@74 575 break;
eric@74 576 default:
eric@74 577 break;
eric@74 578 }
eric@74 579 }
eric@74 580 else
eric@74 581 switch (*bookmark_fmt)
eric@74 582 {
eric@74 583 case '%':
eric@74 584 meta = 1;
eric@74 585 break;
eric@74 586 default:
eric@74 587 *(name++) = *bookmark_fmt;
eric@74 588 }
eric@74 589 bookmark_fmt++;
eric@74 590 }
eric@116 591 *name = '\0';
eric@74 592 }
eric@74 593
eric@74 594
eric@74 595 void main_args (char *out_fn,
eric@74 596 int inf_count,
eric@74 597 char **in_fn,
eric@74 598 char *bookmark_fmt)
eric@49 599 {
eric@49 600 int i, ip;
eric@49 601 input_attributes_t input_attributes;
eric@49 602 pdf_file_attributes_t output_attributes;
eric@74 603 bookmark_t bookmark;
eric@74 604 char bookmark_name [MAX_BOOKMARK_NAME_LEN];
eric@74 605
eric@74 606 bookmark.next = NULL;
eric@74 607 bookmark.level = 1;
eric@74 608 bookmark.name = & bookmark_name [0];
eric@49 609
eric@49 610 memset (& input_attributes, 0, sizeof (input_attributes));
eric@49 611 memset (& output_attributes, 0, sizeof (output_attributes));
eric@49 612
eric@121 613 output_attributes.has_bookmarks = (bookmark_fmt != NULL);
eric@121 614
eric@49 615 if (! open_pdf_output_file (out_fn, & output_attributes))
eric@49 616 fatal (3, "error opening output file \"%s\"\n", out_fn);
eric@49 617 for (i = 0; i < inf_count; i++)
eric@49 618 {
eric@49 619 if (! open_tiff_input_file (in_fn [i]))
eric@49 620 fatal (3, "error opening input file \"%s\"\n", in_fn [i]);
eric@49 621 for (ip = 1;; ip++)
eric@49 622 {
eric@62 623 fprintf (stderr, "processing page %d of file \"%s\"\r", ip, in_fn [i]);
eric@74 624 if (bookmark_fmt)
eric@74 625 generate_bookmark_name (& bookmark_name [0],
eric@74 626 bookmark_fmt,
eric@74 627 in_fn [i],
eric@74 628 ip);
eric@74 629 if (! process_page (ip, input_attributes,
eric@74 630 bookmark_fmt ? & bookmark : NULL))
eric@49 631 fatal (3, "error processing page %d of input file \"%s\"\n", ip, in_fn [i]);
eric@49 632 if (last_tiff_page ())
eric@49 633 break;
eric@49 634 }
eric@49 635 if (verbose)
eric@49 636 fprintf (stderr, "processed %d pages of input file \"%s\"\n", ip, in_fn [i]);
eric@49 637 if (! close_tiff_input_file ())
eric@49 638 fatal (3, "error closing input file \"%s\"\n", in_fn [i]);
eric@49 639 }
eric@49 640 if (! close_pdf_output_files ())
eric@49 641 fatal (3, "error closing output file \"%s\"\n", out_fn);
eric@49 642 }
eric@49 643
eric@49 644
eric@49 645 void main_spec (char *spec_fn)
eric@49 646 {
eric@49 647 if (! parse_spec_file (spec_fn))
eric@49 648 fatal (2, "error parsing spec file\n");
eric@49 649 if (! process_specs ())
eric@49 650 fatal (3, "error processing spec file\n");
eric@49 651 }
eric@49 652
eric@49 653
eric@10 654 int main (int argc, char *argv[])
eric@10 655 {
eric@49 656 char *spec_fn = NULL;
eric@49 657 char *out_fn = NULL;
eric@62 658 char *bookmark_fmt = NULL;
eric@49 659 int inf_count = 0;
eric@49 660 char *in_fn [MAX_INPUT_FILES];
eric@49 661
eric@49 662 progname = argv [0];
eric@10 663
eric@62 664 pdf_init ();
eric@10 665
eric@49 666 while (--argc)
eric@10 667 {
eric@49 668 if (argv [1][0] == '-')
eric@49 669 {
eric@49 670 if (strcmp (argv [1], "-v") == 0)
eric@49 671 verbose++;
eric@49 672 else if (strcmp (argv [1], "-o") == 0)
eric@49 673 {
eric@49 674 if (argc)
eric@49 675 {
eric@49 676 argc--;
eric@49 677 argv++;
eric@49 678 out_fn = argv [1];
eric@49 679 }
eric@49 680 else
eric@49 681 fatal (1, "missing filename after \"-o\" option\n");
eric@49 682 }
eric@49 683 else if (strcmp (argv [1], "-s") == 0)
eric@49 684 {
eric@49 685 if (argc)
eric@49 686 {
eric@49 687 argc--;
eric@49 688 argv++;
eric@49 689 spec_fn = argv [1];
eric@49 690 }
eric@49 691 else
eric@49 692 fatal (1, "missing filename after \"-s\" option\n");
eric@49 693 }
eric@62 694 else if (strcmp (argv [1], "-b") == 0)
eric@62 695 {
eric@62 696 if (argc)
eric@62 697 {
eric@62 698 argc--;
eric@62 699 argv++;
eric@62 700 bookmark_fmt = argv [1];
eric@62 701 }
eric@62 702 else
eric@62 703 fatal (1, "missing format string after \"-b\" option\n");
eric@62 704 }
eric@49 705 else
eric@49 706 fatal (1, "unrecognized option \"%s\"\n", argv [1]);
eric@49 707 }
eric@49 708 else if (inf_count < MAX_INPUT_FILES)
eric@49 709 in_fn [inf_count++] = argv [1];
eric@49 710 else
eric@49 711 fatal (1, "exceeded maximum of %d input files\n", MAX_INPUT_FILES);
eric@49 712 argv++;
eric@10 713 }
eric@10 714
eric@49 715 if (! ((! out_fn) ^ (! spec_fn)))
eric@49 716 fatal (1, "either a spec file or an output file (but not both) must be specified\n");
eric@49 717
eric@49 718 if (out_fn && ! inf_count)
eric@49 719 fatal (1, "no input files specified\n");
eric@26 720
eric@49 721 if (spec_fn && inf_count)
eric@49 722 fatal (1, "if spec file is provided, input files can't be specified as arguments\n");
eric@49 723
eric@49 724 if (spec_fn)
eric@49 725 main_spec (spec_fn);
eric@49 726 else
eric@74 727 main_args (out_fn, inf_count, in_fn, bookmark_fmt);
eric@17 728
eric@10 729 close_tiff_input_file ();
eric@26 730 close_pdf_output_files ();
eric@49 731 exit (0);
eric@10 732 }