From 7e6f49d4648523a4acebf5c03f660bf4a33008b8 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Thu, 10 Apr 2003 08:47:30 +0000 Subject: [PATCH] first cut at PBM support. --- Makefile | 10 +-- tumble.c | 3 +- tumble_input.h | 3 +- tumble_pbm.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 tumble_pbm.c diff --git a/Makefile b/Makefile index cefc29d..4fa0c89 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # tumble: build a PDF file from image files # Makefile -# $Id: Makefile,v 1.39 2003/03/25 01:38:08 eric Exp $ +# $Id: Makefile,v 1.40 2003/04/10 00:47:30 eric Exp $ # Copyright 2001, 2002, 2003 Eric Smith # # This program is free software; you can redistribute it and/or modify @@ -30,7 +30,7 @@ CFLAGS = -Wall LDFLAGS = -LDLIBS = -ltiff -ljpeg -lz -lm +LDLIBS = -ltiff -ljpeg -lpbm -lz -lm ifdef DEBUG CFLAGS := $(CFLAGS) -g @@ -57,14 +57,14 @@ YFLAGS = -d -v # let me know why so I can improve this Makefile. # ----------------------------------------------------------------------------- -VERSION = 0.32 +VERSION = 0.33 PACKAGE = tumble TARGETS = tumble CSRCS = tumble.c semantics.c \ - tumble_input.c tumble_tiff.c tumble_jpeg.c \ + tumble_input.c tumble_tiff.c tumble_jpeg.c tumble_pbm.c \ bitblt.c bitblt_table_gen.c bitblt_g4.c g4_table_gen.c \ pdf.c pdf_util.c pdf_prim.c pdf_name_tree.c \ pdf_bookmark.c pdf_page_label.c \ @@ -92,7 +92,7 @@ all: $(TARGETS) $(TEST_TARGETS) tumble: tumble.o semantics.o \ - tumble_input.o tumble_tiff.o tumble_jpeg.o \ + tumble_input.o tumble_tiff.o tumble_jpeg.o tumble_pbm.o \ scanner.o parser.tab.o \ bitblt.o bitblt_g4.o bitblt_tables.o g4_tables.o \ pdf.o pdf_util.o pdf_prim.o pdf_name_tree.o \ diff --git a/tumble.c b/tumble.c index f862ea5..e4121cb 100644 --- a/tumble.c +++ b/tumble.c @@ -2,7 +2,7 @@ * tumble: build a PDF file from image files * * Main program - * $Id: tumble.c,v 1.41 2003/03/20 08:23:37 eric Exp $ + * $Id: tumble.c,v 1.42 2003/04/10 00:47:30 eric Exp $ * Copyright 2001, 2002, 2003 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -366,6 +366,7 @@ int main (int argc, char *argv[]) init_tiff_handler (); init_jpeg_handler (); + init_pbm_handler (); while (--argc) { diff --git a/tumble_input.h b/tumble_input.h index 6bb2844..c16dd13 100644 --- a/tumble_input.h +++ b/tumble_input.h @@ -1,7 +1,7 @@ /* * tumble: build a PDF file from image files * - * $Id: tumble_input.h,v 1.2 2003/03/20 06:55:27 eric Exp $ + * $Id: tumble_input.h,v 1.3 2003/04/10 00:47:30 eric Exp $ * Copyright 2003 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -64,3 +64,4 @@ bool process_image (int image, void init_tiff_handler (void); void init_jpeg_handler (void); +void init_pbm_handler (void); diff --git a/tumble_pbm.c b/tumble_pbm.c new file mode 100644 index 0000000..cc48dc0 --- /dev/null +++ b/tumble_pbm.c @@ -0,0 +1,230 @@ +/* + * tumble: build a PDF file from image files + * + * $Id: tumble_pbm.c,v 1.1 2003/04/10 00:47:30 eric Exp $ + * Copyright 2001, 2002, 2003 Eric Smith + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. Note that permission is + * not granted to redistribute this program under the terms of any + * other version of the General Public License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA + */ + + +#include +#include +#include +#include +#include /* strcasecmp() is a BSDism */ + +#include +/* + * pbm_readpbmrow_packed always uses big-endian bit ordering. + * On little-endian processors (such as the x86), we want little-endian + * bit order, so we must reverse the bits ourselves after we read in the + * file. + */ +#define PBM_REVERSE_BITS + + +#include "semantics.h" +#include "tumble.h" +#include "bitblt.h" +#include "pdf.h" +#include "tumble_input.h" + + +typedef struct +{ + FILE *f; + int rows; + int cols; + int format; +} pbm_info_t; + +static pbm_info_t pbm; + + +#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0) + + +static bool match_pbm_suffix (char *suffix) +{ + return (strcasecmp (suffix, ".pbm") == 0); +} + + +static bool close_pbm_input_file (void) +{ + pbm.f = NULL; + return (1); +} + + +static bool open_pbm_input_file (FILE *f, char *name) +{ + uint8_t buf [2]; + size_t l; + + l = fread (& buf [0], 1, sizeof (buf), f); + if (l != sizeof (buf)) + return (0); + + rewind (f); + + if (! (((buf [0] == 'P') && (buf [1] == '1')) || + ((buf [0] == 'P') && (buf [1] == '4')))) + return (0); + + pbm.f = f; + + pbm_readpbminit (f, & pbm.cols, & pbm.rows, & pbm.format); + + return (1); +} + + +static bool last_pbm_input_page (void) +{ + /* only handle single-page PBM files for now */ + return (1); +} + + +static bool get_pbm_image_info (int image, + input_attributes_t input_attributes, + image_info_t *image_info) +{ + double x_resolution = 300; + double y_resolution = 300; + + /* $$$ need to handle rotation! */ + if (input_attributes.has_resolution) + { + x_resolution = input_attributes.x_resolution; + y_resolution = input_attributes.y_resolution; + } + + image_info->width_points = (pbm.cols / x_resolution) * POINTS_PER_INCH; + image_info->height_points = (pbm.rows / y_resolution) * POINTS_PER_INCH; + + if ((image_info->height_points > PAGE_MAX_POINTS) || + (image_info->width_points > PAGE_MAX_POINTS)) + { + fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES); + return (0); + } + + return (1); +} + + +static bool process_pbm_image (int image, /* range 1 .. n */ + input_attributes_t input_attributes, + image_info_t *image_info, + pdf_page_handle page) +{ + bool result = 0; + Rect rect; + Bitmap *bitmap = NULL; + + int row; + + rect.min.x = 0; + rect.min.y = 0; + + if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270)) + { + rect.max.x = image_info->height_samples; + rect.max.y = image_info->width_samples; + } + else + { + rect.max.x = image_info->width_samples; + rect.max.y = image_info->height_samples; + } + + bitmap = create_bitmap (& rect); + + if (! bitmap) + { + fprintf (stderr, "can't allocate bitmap\n"); + fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples); + goto fail; + } + + for (row = 0; row < rect.max.y; row++) + { + pbm_readpbmrow_packed (pbm.f, + (unsigned char *) (bitmap->bits + row * bitmap->row_words), + pbm.cols, + pbm.format); + } + +#ifdef PBM_REVERSE_BITS + reverse_bits ((uint8_t *) bitmap->bits, + rect.max.y * bitmap->row_words * sizeof (word_t)); +#endif /* PBM_REVERSE_BITS */ + + /* $$$ need to invert bits here */ + +#if 0 + if (input_attributes.has_page_size) + bitmap = resize_bitmap (bitmap, + x_resolution, + y_resolution, + input_attributes); +#endif + +#if 0 + rotate_bitmap (bitmap, + input_attributes); +#endif + + pdf_write_g4_fax_image (page, + 0, 0, /* x, y */ + image_info->width_points, image_info->height_points, + bitmap, + 0, /* ImageMask */ + 0, 0, 0, /* r, g, b */ + 0); /* BlackIs1 */ + + result = 1; + + fail: + if (bitmap) + free_bitmap (bitmap); + return (result); +} + + +input_handler_t pbm_handler = + { + match_pbm_suffix, + open_pbm_input_file, + close_pbm_input_file, + last_pbm_input_page, + get_pbm_image_info, + process_pbm_image + }; + + +void init_pbm_handler (void) +{ + /* why should we let libpbm look at the real args? */ + int fake_argc = 1; + char *fake_argv [] = { "tumble" }; + + pbm_init (& fake_argc, fake_argv); + install_input_handler (& pbm_handler); +}