From 39101afa09da204cd7487550b086512f3ff59c5a Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Tue, 1 Jan 2002 10:16:50 +0000 Subject: [PATCH] added start of page size support. --- parser.y | 32 +++++++---- scanner.l | 22 ++++---- semantics.c | 77 +++++++++++++++++++++++---- semantics.h | 1 + t2p.c | 150 +++++++++++++++++++++++++++++++++++++++++++--------- t2p.h | 7 ++- tumble.c | 150 +++++++++++++++++++++++++++++++++++++++++++--------- tumble.h | 7 ++- 8 files changed, 361 insertions(+), 85 deletions(-) diff --git a/parser.y b/parser.y index c13d4cd..3ece0ac 100644 --- a/parser.y +++ b/parser.y @@ -59,10 +59,12 @@ %type unit - - %type length +%type orientation + +%type page_size + %% statements: @@ -96,9 +98,9 @@ rotate_clause: ROTATE INTEGER ';' { input_set_rotation ($2) } ; unit: - /* empty */ /* default to INCH */ { $$ = 25.4; } - | CM { $$ = 1.0; } - | INCH { $$ = 25.4; } ; + /* empty */ /* default to INCH */ { $$ = 1.0; } + | CM { $$ = (1.0 / 25.4); } + | INCH { $$ = 1.0; } ; length: FLOAT unit { $$ = $1 * $2; } ; @@ -110,13 +112,23 @@ crop_clause: | CROP length ',' length ',' length ',' length ';' ; orientation: - PORTRAIT - | LANDSCAPE ; + PORTRAIT { $$ = 0; } + | LANDSCAPE { $$ = 1; } ; + +page_size: + PAGE_SIZE { $$ = $1; } + | PAGE_SIZE orientation { if ($2) + { + $$.width = $1.height; + $$.height = $1.width; + } + else + $$ = $1; + } + | length ',' length { $$.width = $1; $$.height = $3; } ; size_clause: - SIZE PAGE_SIZE ';' - | SIZE PAGE_SIZE orientation ';' - | SIZE length ',' length ';' ; + SIZE page_size ';' { input_set_page_size ($2); } ; resolution_clause: RESOLUTION FLOAT unit ; diff --git a/scanner.l b/scanner.l index dc1916d..5535dba 100644 --- a/scanner.l +++ b/scanner.l @@ -1,5 +1,5 @@ /* -$Id: scanner.l,v 1.13 2001/12/31 22:11:43 eric Exp $ +$Id: scanner.l,v 1.14 2002/01/01 02:16:50 eric Exp $ */ %option case-insensitive @@ -32,20 +32,20 @@ dot [\.] {digit}+ { yylval.integer = atoi (yytext); LDBG(("integer %d\n", yylval.integer)); return (INTEGER); } {digit}+\.{digit}+ { yylval.fp = atof (yytext); return (FLOAT); } -a { yylval.size.width = 8.5 * 25.4; - yylval.size.height = 11.0 * 25.4; +a { yylval.size.width = 8.5; + yylval.size.height = 11.0; return (PAGE_SIZE); } -b { yylval.size.width = 11.0 * 25.4; - yylval.size.height = 17.0 * 25.4; +b { yylval.size.width = 11.0; + yylval.size.height = 17.0; return (PAGE_SIZE); } -c { yylval.size.width = 17.0 * 25.4; - yylval.size.height = 22.0 * 25.4; +c { yylval.size.width = 17.0; + yylval.size.height = 22.0; return (PAGE_SIZE); } -d { yylval.size.width = 22.0 * 25.4; - yylval.size.height = 34.0 * 25.4; +d { yylval.size.width = 22.0; + yylval.size.height = 34.0; return (PAGE_SIZE); } -e { yylval.size.width = 34.0 * 25.4; - yylval.size.height = 44.0 * 25.4; +e { yylval.size.width = 34.0; + yylval.size.height = 44.0; return (PAGE_SIZE); } all { return (ALL); } diff --git a/semantics.c b/semantics.c index a3c6278..1af5fed 100644 --- a/semantics.c +++ b/semantics.c @@ -10,8 +10,8 @@ typedef struct { - boolean has_size; - page_size_t size; + boolean has_page_size; + page_size_t page_size; boolean has_rotation; int rotation; @@ -184,6 +184,14 @@ void input_set_rotation (int rotation) SDBG(("rotation %d\n", rotation)); } +void input_set_page_size (page_size_t size) +{ + last_input_context->modifiers [current_modifier_context].has_page_size = 1; + last_input_context->modifiers [current_modifier_context].page_size = size; + printf ("page size %f, %f\n", size.width, size.height); + SDBG(("page size %f, %f\n", size.width, size.height)); +} + static void increment_input_image_count (int count) { input_context_t *context; @@ -423,14 +431,42 @@ static char *get_input_file (input_context_t *context) exit (2); } -static int get_input_rotation (input_context_t *context, input_modifier_type_t type) +static boolean get_input_rotation (input_context_t *context, + input_modifier_type_t type, + int *rotation) { for (; context; context = context->parent) { if (context->modifiers [type].has_rotation) - return (context->modifiers [type].rotation); + { + * rotation = context->modifiers [type].rotation; + return (1); + } if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation) - return (context->modifiers [INPUT_MODIFIER_ALL].rotation); + { + * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation; + return (1); + } + } + return (0); /* default */ +} + +static boolean get_input_page_size (input_context_t *context, + input_modifier_type_t type, + page_size_t *page_size) +{ + for (; context; context = context->parent) + { + if (context->modifiers [type].has_page_size) + { + * page_size = context->modifiers [type].page_size; + return (1); + } + if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size) + { + * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size; + return (1); + } } return (0); /* default */ } @@ -473,10 +509,24 @@ void dump_input_tree (void) for (i = image->range.first; i <= image->range.last; i++) { input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN; - printf ("file '%s' image %d, rotation %d\n", + boolean has_rotation, has_page_size; + int rotation; + page_size_t page_size; + + has_rotation = get_input_rotation (image->input_context, + parity, + & rotation); + has_page_size = get_input_page_size (image->input_context, + parity, + & page_size); + printf ("file '%s' image %d", get_input_file (image->input_context), - i, - get_input_rotation (image->input_context, parity)); + i); + if (has_rotation) + printf (" rotation %d", rotation); + if (has_page_size) + printf (" size %f, %f", page_size.width, page_size.height); + printf ("\n"); } } @@ -611,8 +661,15 @@ boolean process_specs (void) parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN; memset (& input_attributes, 0, sizeof (input_attributes)); - input_attributes.rotation = get_input_rotation (image->input_context, - parity);; + + input_attributes.rotation = 0; + input_attributes.has_rotation = get_input_rotation (image->input_context, + parity, + & input_attributes.rotation); + + input_attributes.has_page_size = get_input_page_size (image->input_context, + parity, + & input_attributes.page_size); process_page (image->range.first + i, input_attributes, diff --git a/semantics.h b/semantics.h index 66ca1ab..6895585 100644 --- a/semantics.h +++ b/semantics.h @@ -52,6 +52,7 @@ void input_pop_context (void); void input_set_modifier_context (input_modifier_type_t type); void input_set_file (char *name); void input_set_rotation (int rotation); +void input_set_page_size (page_size_t size); void input_images (range_t range); /* semantic routines for output statements */ diff --git a/t2p.c b/t2p.c index 7544933..e279847 100644 --- a/t2p.c +++ b/t2p.c @@ -5,7 +5,7 @@ * encoding. * * Main program - * $Id: t2p.c,v 1.11 2001/12/31 22:11:43 eric Exp $ + * $Id: t2p.c,v 1.12 2002/01/01 02:16:50 eric Exp $ * Copyright 2001 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -179,6 +179,42 @@ void process_page_numbers (int page_index, } +static Bitmap *rotate_bitmap (Bitmap *src, int rotation) +{ + Rect src_rect; + Point dest_upper_left; + int scan; + + src_rect.upper_left.x = 0; + src_rect.upper_left.y = 0; + src_rect.lower_right.x = src->width; + src_rect.lower_right.y = src->height; + + dest_upper_left.x = 0; + dest_upper_left.y = 0; + + switch (rotation) + { + case 0: scan = ROT_0; break; + case 90: scan = ROT_90; break; + case 180: scan = ROT_180; break; + case 270: scan = ROT_270; break; + default: + fprintf (stderr, "rotation must be 0, 90, 180, or 270\n"); + return (NULL); + } + + return (bitblt (src, + src_rect, + NULL, /* dest_bitmap */ + dest_upper_left, + scan, + TF_SRC)); +} + + +#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0) + boolean process_page (int image, /* range 1 .. n */ input_attributes_t input_attributes, bookmark_t *bookmarks) @@ -186,6 +222,7 @@ boolean process_page (int image, /* range 1 .. n */ int result = 0; u32 image_length, image_width; + u32 dest_image_length, dest_image_width; #ifdef CHECK_DEPTH u32 image_depth; #endif @@ -193,14 +230,19 @@ boolean process_page (int image, /* range 1 .. n */ u16 samples_per_pixel; u16 bits_per_sample; u16 planar_config; + u16 resolution_unit; float x_resolution, y_resolution; + float dest_x_resolution, dest_y_resolution; + + int scanline_size; + int width_points, height_points; /* really 1/72 inch units rather than points */ - - char *buffer; - u32 row; + Bitmap *src_bitmap; + Bitmap *dest_bitmap; + int row; panda_page *page; @@ -298,6 +340,17 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } + width_points = (image_width / x_resolution) * POINTS_PER_INCH; + height_points = (image_length / y_resolution) * POINTS_PER_INCH; + + if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS)) + { + fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); + goto fail; + } + + printf ("height_points %d, width_points %d\n", height_points, width_points); + tiff_temp_fd = mkstemp (tiff_temp_fn); if (tiff_temp_fd < 0) { @@ -312,47 +365,92 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } - TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, image_length); - TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, image_width); + printf ("rotation %d\n", input_attributes.rotation); + + if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270)) + { + dest_image_width = image_length; + dest_image_length = image_width; + dest_x_resolution = y_resolution; + dest_y_resolution = x_resolution; + SWAP (int, width_points, height_points); + } + else + { + dest_image_width = image_width; + dest_image_length = image_length; + dest_x_resolution = x_resolution; + dest_y_resolution = y_resolution; + } + + TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, dest_image_length); + TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, dest_image_width); TIFFSetField (tiff_temp, TIFFTAG_PLANARCONFIG, planar_config); - TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, image_length); + TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, dest_image_length); TIFFSetField (tiff_temp, TIFFTAG_RESOLUTIONUNIT, resolution_unit); - TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, x_resolution); - TIFFSetField (tiff_temp, TIFFTAG_YRESOLUTION, y_resolution); + TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, dest_x_resolution); + TIFFSetField (tiff_temp, TIFFTAG_YRESOLUTION, dest_y_resolution); TIFFSetField (tiff_temp, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel); TIFFSetField (tiff_temp, TIFFTAG_BITSPERSAMPLE, bits_per_sample); TIFFSetField (tiff_temp, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); TIFFSetField (tiff_temp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); - buffer = _TIFFmalloc (TIFFScanlineSize (in)); - if (! buffer) + scanline_size = TIFFScanlineSize (in); + + src_bitmap = create_bitmap (image_width, image_length); + if (! src_bitmap) { - fprintf (stderr, "failed to allocate buffer\n"); + fprintf (stderr, "can't allocate bitmap\n"); goto fail; } + if (src_bitmap->rowbytes != scanline_size) + { + printf ("image_width %d\n", image_width); + printf ("rowbytes %d\n", src_bitmap->rowbytes); + printf ("TIFFScanlineSize %d\n", scanline_size); + } + for (row = 0; row < image_length; row++) + TIFFReadScanline (in, + src_bitmap->bits + row * src_bitmap->rowbytes, + row, + 0); + + for (row = 0; row < dest_image_length; row++) + if (1 != TIFFReadScanline (in, + src_bitmap->bits + row * src_bitmap->rowbytes, + row, + 0)) + { + fprintf (stderr, "can't read TIFF scanline\n"); + goto fail; + } + + dest_bitmap = rotate_bitmap (src_bitmap, input_attributes.rotation); + if (! dest_bitmap) { - TIFFReadScanline (in, buffer, row, 0); - TIFFWriteScanline (tiff_temp, buffer, row, 0); - } - - _TIFFfree (buffer); - TIFFClose (tiff_temp); - - width_points = (image_width / x_resolution) * POINTS_PER_INCH; - height_points = (image_length / y_resolution) * POINTS_PER_INCH; - - if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS)) - { - fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); + fprintf (stderr, "can't allocate bitmap\n"); goto fail; } - printf ("height_points %d, width_points %d\n", height_points, width_points); + for (row = 0; row < dest_bitmap->height; row++) + if (1 != TIFFWriteScanline (tiff_temp, + dest_bitmap->bits + row * dest_bitmap->rowbytes, + row, + 0)) + { + fprintf (stderr, "can't write TIFF scanline\n"); + goto fail; + } + + TIFFClose (tiff_temp); + + free_bitmap (dest_bitmap); + free_bitmap (src_bitmap); sprintf (pagesize, "[0 0 %d %d]", width_points, height_points); diff --git a/t2p.h b/t2p.h index 32d9eea..ef4d55d 100644 --- a/t2p.h +++ b/t2p.h @@ -1,7 +1,12 @@ typedef struct { - page_size_t size; + boolean has_page_size; + page_size_t page_size; + + boolean has_rotation; int rotation; + + boolean has_crop; crop_t crop; } input_attributes_t; diff --git a/tumble.c b/tumble.c index a68c73a..a7a8b24 100644 --- a/tumble.c +++ b/tumble.c @@ -5,7 +5,7 @@ * encoding. * * Main program - * $Id: tumble.c,v 1.11 2001/12/31 22:11:43 eric Exp $ + * $Id: tumble.c,v 1.12 2002/01/01 02:16:50 eric Exp $ * Copyright 2001 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -179,6 +179,42 @@ void process_page_numbers (int page_index, } +static Bitmap *rotate_bitmap (Bitmap *src, int rotation) +{ + Rect src_rect; + Point dest_upper_left; + int scan; + + src_rect.upper_left.x = 0; + src_rect.upper_left.y = 0; + src_rect.lower_right.x = src->width; + src_rect.lower_right.y = src->height; + + dest_upper_left.x = 0; + dest_upper_left.y = 0; + + switch (rotation) + { + case 0: scan = ROT_0; break; + case 90: scan = ROT_90; break; + case 180: scan = ROT_180; break; + case 270: scan = ROT_270; break; + default: + fprintf (stderr, "rotation must be 0, 90, 180, or 270\n"); + return (NULL); + } + + return (bitblt (src, + src_rect, + NULL, /* dest_bitmap */ + dest_upper_left, + scan, + TF_SRC)); +} + + +#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0) + boolean process_page (int image, /* range 1 .. n */ input_attributes_t input_attributes, bookmark_t *bookmarks) @@ -186,6 +222,7 @@ boolean process_page (int image, /* range 1 .. n */ int result = 0; u32 image_length, image_width; + u32 dest_image_length, dest_image_width; #ifdef CHECK_DEPTH u32 image_depth; #endif @@ -193,14 +230,19 @@ boolean process_page (int image, /* range 1 .. n */ u16 samples_per_pixel; u16 bits_per_sample; u16 planar_config; + u16 resolution_unit; float x_resolution, y_resolution; + float dest_x_resolution, dest_y_resolution; + + int scanline_size; + int width_points, height_points; /* really 1/72 inch units rather than points */ - - char *buffer; - u32 row; + Bitmap *src_bitmap; + Bitmap *dest_bitmap; + int row; panda_page *page; @@ -298,6 +340,17 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } + width_points = (image_width / x_resolution) * POINTS_PER_INCH; + height_points = (image_length / y_resolution) * POINTS_PER_INCH; + + if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS)) + { + fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); + goto fail; + } + + printf ("height_points %d, width_points %d\n", height_points, width_points); + tiff_temp_fd = mkstemp (tiff_temp_fn); if (tiff_temp_fd < 0) { @@ -312,47 +365,92 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } - TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, image_length); - TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, image_width); + printf ("rotation %d\n", input_attributes.rotation); + + if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270)) + { + dest_image_width = image_length; + dest_image_length = image_width; + dest_x_resolution = y_resolution; + dest_y_resolution = x_resolution; + SWAP (int, width_points, height_points); + } + else + { + dest_image_width = image_width; + dest_image_length = image_length; + dest_x_resolution = x_resolution; + dest_y_resolution = y_resolution; + } + + TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, dest_image_length); + TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, dest_image_width); TIFFSetField (tiff_temp, TIFFTAG_PLANARCONFIG, planar_config); - TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, image_length); + TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, dest_image_length); TIFFSetField (tiff_temp, TIFFTAG_RESOLUTIONUNIT, resolution_unit); - TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, x_resolution); - TIFFSetField (tiff_temp, TIFFTAG_YRESOLUTION, y_resolution); + TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, dest_x_resolution); + TIFFSetField (tiff_temp, TIFFTAG_YRESOLUTION, dest_y_resolution); TIFFSetField (tiff_temp, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel); TIFFSetField (tiff_temp, TIFFTAG_BITSPERSAMPLE, bits_per_sample); TIFFSetField (tiff_temp, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); TIFFSetField (tiff_temp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); - buffer = _TIFFmalloc (TIFFScanlineSize (in)); - if (! buffer) + scanline_size = TIFFScanlineSize (in); + + src_bitmap = create_bitmap (image_width, image_length); + if (! src_bitmap) { - fprintf (stderr, "failed to allocate buffer\n"); + fprintf (stderr, "can't allocate bitmap\n"); goto fail; } + if (src_bitmap->rowbytes != scanline_size) + { + printf ("image_width %d\n", image_width); + printf ("rowbytes %d\n", src_bitmap->rowbytes); + printf ("TIFFScanlineSize %d\n", scanline_size); + } + for (row = 0; row < image_length; row++) + TIFFReadScanline (in, + src_bitmap->bits + row * src_bitmap->rowbytes, + row, + 0); + + for (row = 0; row < dest_image_length; row++) + if (1 != TIFFReadScanline (in, + src_bitmap->bits + row * src_bitmap->rowbytes, + row, + 0)) + { + fprintf (stderr, "can't read TIFF scanline\n"); + goto fail; + } + + dest_bitmap = rotate_bitmap (src_bitmap, input_attributes.rotation); + if (! dest_bitmap) { - TIFFReadScanline (in, buffer, row, 0); - TIFFWriteScanline (tiff_temp, buffer, row, 0); - } - - _TIFFfree (buffer); - TIFFClose (tiff_temp); - - width_points = (image_width / x_resolution) * POINTS_PER_INCH; - height_points = (image_length / y_resolution) * POINTS_PER_INCH; - - if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS)) - { - fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); + fprintf (stderr, "can't allocate bitmap\n"); goto fail; } - printf ("height_points %d, width_points %d\n", height_points, width_points); + for (row = 0; row < dest_bitmap->height; row++) + if (1 != TIFFWriteScanline (tiff_temp, + dest_bitmap->bits + row * dest_bitmap->rowbytes, + row, + 0)) + { + fprintf (stderr, "can't write TIFF scanline\n"); + goto fail; + } + + TIFFClose (tiff_temp); + + free_bitmap (dest_bitmap); + free_bitmap (src_bitmap); sprintf (pagesize, "[0 0 %d %d]", width_points, height_points); diff --git a/tumble.h b/tumble.h index 32d9eea..ef4d55d 100644 --- a/tumble.h +++ b/tumble.h @@ -1,7 +1,12 @@ typedef struct { - page_size_t size; + boolean has_page_size; + page_size_t page_size; + + boolean has_rotation; int rotation; + + boolean has_crop; crop_t crop; } input_attributes_t;