From 684055a0fcd2390d22ed8f3230472a1f51f44b51 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Tue, 22 Jan 2002 09:42:42 +0000 Subject: [PATCH] *** empty log message *** --- Makefile | 4 +- TODO | 3 +- bitblt.c | 299 ++++++++++++++++++++++++++++++++++++++++++-------- bitblt.h | 14 ++- bitblt_test.c | 28 +++-- t2p.c | 25 +---- tumble.c | 25 +---- 7 files changed, 294 insertions(+), 104 deletions(-) diff --git a/Makefile b/Makefile index ed6931f..0f370b4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # tiff2pdf: build a PDF file out of one or more TIFF Class F Group 4 files # Makefile -# $Id: Makefile,v 1.7 2001/12/30 23:24:50 eric Exp $ +# $Id: Makefile,v 1.8 2002/01/22 01:41:12 eric Exp $ # Copyright 2001 Eric Smith # # This program is free software; you can redistribute it and/or modify @@ -34,7 +34,7 @@ AUTO_SRCS = scanner.c parser.tab.c AUTO_HDRS = parser.tab.h AUTO_MISC = parser.output -tiff2pdf: tiff2pdf.o scanner.o semantics.o parser.tab.o +tiff2pdf: tiff2pdf.o scanner.o semantics.o parser.tab.o bitblt.o bitblt_test: bitblt_test.o bitblt.o diff --git a/TODO b/TODO index 3988553..a3d6bf0 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ tiff2pdf TODO list -$Id: TODO,v 1.4 2002/01/02 05:49:42 eric Exp $ +$Id: TODO,v 1.5 2002/01/22 01:40:59 eric Exp $ No particular order. Page numbers refer to _Portable Document Format Reference Manual_ by Adobe Systems Incorporated, Addison-Wesley, 1993. @@ -7,6 +7,7 @@ Reference Manual_ by Adobe Systems Incorporated, Addison-Wesley, 1993. ----------------------------------------------------------------------------- * bitblt library: * optimize + * replace inner loops in flip_h and flip_v with Duff's Device * check for endian problems * crop diff --git a/bitblt.c b/bitblt.c index b62f136..18a47e5 100644 --- a/bitblt.c +++ b/bitblt.c @@ -6,7 +6,7 @@ #include "bitblt.h" -#define CALC_ROWBYTES(width) (((width) - 1) / 8 + 1) +#define DIV_ROUND_UP(count,pow2) (((count) - 1) / (pow2) + 1) static const u8 bit_reverse_byte [0x100] = @@ -45,8 +45,16 @@ static const u8 bit_reverse_byte [0x100] = 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; +static word_type bit_reverse_word (word_type d) +{ + return (bit_reverse_byte [d >> 24] | + (bit_reverse_byte [(d >> 16) & 0xff] << 8) | + (bit_reverse_byte [(d >> 8) & 0xff] << 16) | + (bit_reverse_byte [d & 0xff] << 24)); +} -static u8 *temp_buffer; + +static u32 *temp_buffer; static u32 temp_buffer_size; static void realloc_temp_buffer (u32 size) @@ -63,12 +71,12 @@ static void realloc_temp_buffer (u32 size) } -static inline u8 pixel_mask (x) +static inline word_type pixel_mask (x) { #ifdef LSB_LEFT return (1 << x); #else - return (1 << (7 - x)); + return (1 << ((BITS_PER_WORD - 1) - x)); #endif }; @@ -85,8 +93,8 @@ Bitmap *create_bitmap (Rect *rect) if (! bitmap) return (NULL); bitmap->rect = * rect; - bitmap->rowbytes = CALC_ROWBYTES (width); - bitmap->bits = calloc (height * bitmap->rowbytes, 1); + bitmap->row_words = DIV_ROUND_UP (width, BITS_PER_WORD); + bitmap->bits = calloc (1, height * bitmap->row_words * sizeof (word_type)); if (! bitmap->bits) { free (bitmap); @@ -103,33 +111,33 @@ void free_bitmap (Bitmap *bitmap) boolean get_pixel (Bitmap *bitmap, Point coord) { - u8 *p; + word_type *p; if ((coord.x < bitmap->rect.min.x) || (coord.x >= bitmap->rect.max.x) || (coord.y < bitmap->rect.min.y) || (coord.y >= bitmap->rect.max.y)) return (0); p = bitmap->bits + - (coord.y - bitmap->rect.min.y) * bitmap->rowbytes + - (coord.x - bitmap->rect.min.x) / 8; - return ((*p & pixel_mask (coord.x & 7)) != 0); + (coord.y - bitmap->rect.min.y) * bitmap->row_words + + (coord.x - bitmap->rect.min.x) / BITS_PER_WORD; + return ((*p & pixel_mask (coord.x & (BITS_PER_WORD - 1))) != 0); } void set_pixel (Bitmap *bitmap, Point coord, boolean value) { - u8 *p; + word_type *p; if ((coord.x < bitmap->rect.min.x) || (coord.x >= bitmap->rect.max.x) || (coord.y < bitmap->rect.min.y) || (coord.y >= bitmap->rect.max.y)) return; p = bitmap->bits + - (coord.y - bitmap->rect.min.y) * bitmap->rowbytes + - (coord.x - bitmap->rect.min.x) / 8; + (coord.y - bitmap->rect.min.y) * bitmap->row_words + + (coord.x - bitmap->rect.min.x) / BITS_PER_WORD; if (value) - *p |= pixel_mask (coord.x & 7); + *p |= pixel_mask (coord.x & (BITS_PER_WORD - 1)); else - *p &= (0xff ^ pixel_mask (coord.x & 7)); + *p &= ~pixel_mask (coord.x & (BITS_PER_WORD - 1)); } @@ -166,11 +174,210 @@ static boolean clip_rect (Rect *rect1, Rect *rect2) } +#if 0 +static void blt_background (Bitmap *dest_bitmap, + Rect *dest_rect) +{ + s32 y; + word_type *rp; + + /* This function requires a non-null dest rect */ + assert (dest_rect->min.x < dest_rect->max.x); + assert (dest_rect->min.y < dest_rect->max.y); + + /* and that the rows of the dest rect lie entirely within the dest bitmap */ + assert (dest_rect->min.y >= dest_bitmap->rect->min.y); + assert (dest_rect->max.y <= dest_bitmap->rect->max.y); + + /* clip the x axis of the dest_rect to the bounds of the dest bitmap */ + if (dest_rect->min.x < dest_bitmap->rect.min.x) + dest_rect->min.x = dest_bitmap->rect.min.x; + if (dest_rect->max.x > dest_bitmap->rect.max.x) + dest_rect->max.x = dest_bitmap->rect.max.x; + + rp = ???; + for (y = 0; y < rect_height (dest_rect); y++) + { + ???; + rp += dest_bitmap->row_words; + } +} + + +static void blt (Bitmap *src_bitmap, + Rect *src_rect, + Bitmap *dest_bitmap, + Rect *dest_rect) +{ + s32 y; + word_type *rp; + + /* This function requires a non-null src rect */ + assert (dest_rect->min.x < dest_rect->max.x); + assert (dest_rect->min.y < dest_rect->max.y); + + /* and a non-null dest rect */ + assert (dest_rect->min.x < dest_rect->max.x); + assert (dest_rect->min.y < dest_rect->max.y); + + /* and that the widths and heights of the rects match */ + assert (rect_width (src_rect) == rect_width (dest_rect)); + assert (rect_height (src_rect) == rect_height (dest_rect)); + + /* and that the rows of the src rect lie entirely within the src bitmap */ + assert (dest_rect->min.y >= dest_bitmap->rect->min.y); + assert (dest_rect->max.y <= dest_bitmap->rect->max.y); + + /* and that the rows of the dest rect lie entirely within the dest bitmap */ + assert (dest_rect->min.y >= dest_bitmap->rect->min.y); + assert (dest_rect->max.y <= dest_bitmap->rect->max.y); + + /* clip the x axis of the dest_rect to the bounds of the dest bitmap, + and adjust the src_rect to match */ + if (dest_rect->min.x < dest_bitmap->rect.min.x) + { + src_rect->min.x += ???; + dest_rect->min.x = dest_bitmap->rect.min.x; + } + if (dest_rect->max.x > dest_bitmap->rect.max.x) + { + dest_rect->max.x = dest_bitmap->rect.max.x; + } + + rp = ???; + for (y = 0; y < rect_height (dest_rect); y++) + { + ???; + rp += dest_bitmap->row_words; + } +} + + Bitmap *bitblt (Bitmap *src_bitmap, Rect *src_rect, Bitmap *dest_bitmap, Point *dest_min, - int tfn) + int tfn, + int background) +{ + Rect sr, dr; /* src and dest rects, clipped to visible portion of + dest rect */ + u32 drw, drh; /* dest rect width, height - gets adjusted */ + Point src_point, dest_point; + + { + sr = * src_rect; + + u32 srw = rect_width (& sr); + u32 srh = rect_height (& sr); + + if ((srw < 0) || (srh < 0)) + goto done; /* the source rect is empty! */ + + dr.min = * dest_min; + dr.max.x = dr.min.x + srw; + dr.max.y = dr.min.y + srh; + } + + if (! dest_bitmap) + { + dest_bitmap = create_bitmap (& dr); + if (! dest_bitmap) + return (NULL); + } + + if ((dr.min.x >= dest_bitmap->rect.max.x) || + (dr.min.y >= dest_bitmap->rect.max.y)) + goto done; /* the dest rect isn't even in the dest bitmap! */ + + /* crop dest rect to dest bitmap */ + + delta = dest_bitmap->rect.min.x - dr.min.x; + if (delta > 0) + { + sr.min.x += delta; + dr.min.x += delta; + } + + delta = dest_bitmap->rect.min.y - dr.min.y; + if (delta > 0) + { + sr.min.y += delta; + dr.min.y += delta; + } + + delta = dr.max.x - dest_bitmap->rect.max.x; + if (delta > 0) + { + sr.max.x -= delta; + dr.max.x -= delta; + } + + delta = dr.max.y - dest_bitmap->rect.max.y; + if (delta > 0) + { + sr.max.x -= delta; + dr.max.x -= delta; + } + + drw = rect_width (& dr); + drh = rect_height (& dh); + + /* if the source rect min y is >= the source bitmap max y, + we transfer background color to the entire dest rect */ + if (sr.min.y >= src->rect.max.y) + { + blt_background (dest_bitmap, & dr); + goto done; + } + + /* if the source rect min y is less than the source bitmap min y, + we need to transfer some backgound color to the top part of the dest + rect */ + if (sr.min.y < src->rect.min.y) + { + Rect dr2; + uint32 bg_height; + + bg_height = src->rect.min.y - sr.min.y; + if (bg_height > sh) + bg_height = sh; + + dr2 = dr; + dr2.max.y = dr2.min.y + bg_height; + + blt_background (dest_bitmap, & dr2); + + /* now reduce the rect height by the number of lines of background + color */ + sr.min.y += bg_height; + dr.min.y += bg_height; + sh -= bg_height; + dh -= bg_height; + + if (sr.min.y == sr.max.y) + goto done; + } + + /* now blt the available rows of the source rect */ + + /* now transfer the background color to any remaining rows of the + dest rect */ + if (??? ) + { + blt_background (dest_bitmap, & dr); + } + + done: + return (dest_bitmap); +} +#else +Bitmap *bitblt (Bitmap *src_bitmap, + Rect *src_rect, + Bitmap *dest_bitmap, + Point *dest_min, + int tfn, + int background) { Point src_point, dest_point; @@ -206,73 +413,77 @@ Bitmap *bitblt (Bitmap *src_bitmap, } return (dest_bitmap); } +#endif /* in-place transformations */ void flip_h (Bitmap *src) { - u8 *rp; /* row pointer */ - u8 *p1; /* work src ptr */ - u8 *p2; /* work dest ptr */ - u16 d; + word_type *rp; /* row pointer */ + word_type *p1; /* work src ptr */ + word_type *p2; /* work dest ptr */ s32 y; - int shift; + int shift1, shift2; - realloc_temp_buffer (src->rowbytes + 1); + realloc_temp_buffer ((src->row_words + 1) * sizeof (word_type)); rp = src->bits; if ((rect_width (& src->rect) & 7) == 0) { for (y = src->rect.min.y; y < src->rect.max.y; y++) { - memcpy (temp_buffer, rp, src->rowbytes); - p1 = temp_buffer + src->rowbytes - 1; + memcpy (temp_buffer, rp, src->row_words * sizeof (word_type)); + p1 = temp_buffer + src->row_words; p2 = rp; while (p1 >= temp_buffer) - *(p2++) = bit_reverse_byte [*(p1--)]; + *(p2++) = bit_reverse_word (*(p1--)); - rp += src->rowbytes; + rp += src->row_words; } return; } temp_buffer [0] = 0; - shift = 8 - (rect_width (& src->rect) & 7); + shift1 = rect_width (& src->rect) & (BITS_PER_WORD - 1); + shift2 = BITS_PER_WORD - shift1; for (y = src->rect.min.y; y < src->rect.max.y; y++) { - memcpy (temp_buffer + 1, rp, src->rowbytes); - p1 = temp_buffer + src->rowbytes; + word_type d1, d2; + + memcpy (temp_buffer + 1, rp, src->row_words * sizeof (word_type)); + p1 = temp_buffer + src->row_words; p2 = rp; - d = *(p1--); + d2 = *(p1--); while (p1 >= temp_buffer) { - d = (d >> 8) | ((*(p1--)) << 8); - *(p2++) = bit_reverse_byte [(d >> shift) & 0xff]; + d1 = *(p1--); + *(p2++) = bit_reverse_word ((d1 << shift1) | (d2 >> shift2)); + d2 = d1; } - rp += src->rowbytes; + rp += src->row_words; } } void flip_v (Bitmap *src) { - u8 *p1, *p2; + word_type *p1, *p2; - realloc_temp_buffer (src->rowbytes); + realloc_temp_buffer (src->row_words * sizeof (word_type)); p1 = src->bits; - p2 = src->bits + src->rowbytes * (rect_height (& src->rect) - 1); + p2 = src->bits + src->row_words * (rect_height (& src->rect) - 1); while (p1 < p2) { - memcpy (temp_buffer, p1, src->rowbytes); - memcpy (p1, p2, src->rowbytes); - memcpy (p2, temp_buffer, src->rowbytes); - p1 += src->rowbytes; - p2 -= src->rowbytes; + memcpy (temp_buffer, p1, src->row_words * sizeof (word_type)); + memcpy (p1, p2, src->row_words * sizeof (word_type)); + memcpy (p2, temp_buffer, src->row_words * sizeof (word_type)); + p1 += src->row_words; + p2 -= src->row_words; } } @@ -285,10 +496,10 @@ void rot_180 (Bitmap *src) /* combination of flip_h and flip_v */ /* "in-place" transformations - will allocate new memory and free old */ void transpose (Bitmap *src) { - u32 new_rowbytes = CALC_ROWBYTES (rect_height (& src->rect)); - u8 *new_bits; + u32 new_row_words = DIV_ROUND_UP (rect_height (& src->rect), 32); + word_type *new_bits; - new_bits = calloc (1, new_rowbytes * rect_width (& src->rect)); + new_bits = calloc (1, new_row_words * rect_width (& src->rect) * sizeof (word_type)); /* $$$ more code needed here */ } diff --git a/bitblt.h b/bitblt.h index d3fc3a5..c5f4250 100644 --- a/bitblt.h +++ b/bitblt.h @@ -20,11 +20,18 @@ static inline s32 rect_height (Rect *r) return (r->max.y - r->min.y); } +/* + * Despite the following two definitions, there are still some places + * in the code that depend on words having 32 bits. + */ +#define BITS_PER_WORD 32 +typedef u32 word_type; + typedef struct Bitmap { - u8 *bits; + word_type *bits; Rect rect; - u32 rowbytes; + u32 row_words; } Bitmap; @@ -45,7 +52,8 @@ Bitmap *bitblt (Bitmap *src_bitmap, Rect *src_rect, Bitmap *dest_bitmap, Point *dest_min, - int tfn); + int tfn, + int background); /* in-place transformations */ diff --git a/bitblt_test.c b/bitblt_test.c index 90f0a92..5290f7a 100644 --- a/bitblt_test.c +++ b/bitblt_test.c @@ -1,4 +1,5 @@ #include +#include #include "type.h" #include "bitblt.h" @@ -24,8 +25,9 @@ Bitmap *setup (void) { Bitmap *b; Point p; + Rect r = {{ 0, 0 }, { WIDTH, HEIGHT }}; - b = create_bitmap (WIDTH, HEIGHT); + b = create_bitmap (& r); if (! b) return (NULL); @@ -39,10 +41,10 @@ Bitmap *setup (void) void print_bitmap (FILE *o, Bitmap *b) { Point p; - printf ("rowbytes: %d\n", b->rowbytes); - for (p.y = 0; p.y < b->height; p.y++) + printf ("row_words: %d\n", b->row_words); + for (p.y = b->rect.min.y; p.y < b->rect.max.y; p.y++) { - for (p.x = 0; p.x < b->width; p.x++) + for (p.x = b->rect.min.x; p.x < b->rect.max.x; p.x++) fputc (".X" [get_pixel (b, p)], o); fprintf (o, "\n"); } @@ -64,18 +66,19 @@ int main (int argc, char *argv[]) } print_bitmap (stdout, b); + printf ("\n"); + flip_v (b); + + print_bitmap (stdout, b); + printf ("\n"); + + flip_h (b); + + print_bitmap (stdout, b); printf ("\n"); #if 0 - b2 = create_bitmap (b->height, b->width); - if (! b2) - { - fprintf (stderr, "create_bitmap failed\n"); - exit (2); - } -#endif - r.upper_left.x = r.upper_left.y = 0; r.lower_right.x = b->width; r.lower_right.y = b->height; @@ -92,6 +95,7 @@ int main (int argc, char *argv[]) } print_bitmap (stdout, b2); +#endif exit (0); } diff --git a/t2p.c b/t2p.c index f628718..3ea2df8 100644 --- a/t2p.c +++ b/t2p.c @@ -5,7 +5,7 @@ * encoding. * * Main program - * $Id: t2p.c,v 1.14 2002/01/02 08:39:39 eric Exp $ + * $Id: t2p.c,v 1.15 2002/01/22 01:42:42 eric Exp $ * Copyright 2001 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -200,7 +200,7 @@ static Bitmap *resize_bitmap (Bitmap *src, dest_min.x = 0; dest_min.y = 0; - dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC); + dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0); free_bitmap (src); return (dest); } @@ -244,8 +244,6 @@ boolean process_page (int image, /* range 1 .. n */ 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 */ @@ -358,8 +356,6 @@ boolean process_page (int image, /* range 1 .. n */ dest_y_resolution = y_resolution; } - scanline_size = TIFFScanlineSize (in); - rect.min.x = 0; rect.min.y = 0; rect.max.x = image_width; @@ -373,22 +369,9 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } - if (bitmap->rowbytes != scanline_size) - { - printf ("image_width %d\n", image_width); - printf ("rowbytes %d\n", bitmap->rowbytes); - printf ("TIFFScanlineSize %d\n", scanline_size); - } - for (row = 0; row < image_length; row++) - TIFFReadScanline (in, - bitmap->bits + row * bitmap->rowbytes, - row, - 0); - - for (row = 0; row < dest_image_length; row++) if (1 != TIFFReadScanline (in, - bitmap->bits + row * bitmap->rowbytes, + bitmap->bits + row * bitmap->row_words, row, 0)) { @@ -435,7 +418,7 @@ boolean process_page (int image, /* range 1 .. n */ for (row = 0; row < rect_height (& bitmap->rect); row++) if (1 != TIFFWriteScanline (tiff_temp, - bitmap->bits + row * bitmap->rowbytes, + bitmap->bits + row * bitmap->row_words, row, 0)) { diff --git a/tumble.c b/tumble.c index 10e16ef..2ede349 100644 --- a/tumble.c +++ b/tumble.c @@ -5,7 +5,7 @@ * encoding. * * Main program - * $Id: tumble.c,v 1.14 2002/01/02 08:39:39 eric Exp $ + * $Id: tumble.c,v 1.15 2002/01/22 01:42:42 eric Exp $ * Copyright 2001 Eric Smith * * This program is free software; you can redistribute it and/or modify @@ -200,7 +200,7 @@ static Bitmap *resize_bitmap (Bitmap *src, dest_min.x = 0; dest_min.y = 0; - dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC); + dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0); free_bitmap (src); return (dest); } @@ -244,8 +244,6 @@ boolean process_page (int image, /* range 1 .. n */ 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 */ @@ -358,8 +356,6 @@ boolean process_page (int image, /* range 1 .. n */ dest_y_resolution = y_resolution; } - scanline_size = TIFFScanlineSize (in); - rect.min.x = 0; rect.min.y = 0; rect.max.x = image_width; @@ -373,22 +369,9 @@ boolean process_page (int image, /* range 1 .. n */ goto fail; } - if (bitmap->rowbytes != scanline_size) - { - printf ("image_width %d\n", image_width); - printf ("rowbytes %d\n", bitmap->rowbytes); - printf ("TIFFScanlineSize %d\n", scanline_size); - } - for (row = 0; row < image_length; row++) - TIFFReadScanline (in, - bitmap->bits + row * bitmap->rowbytes, - row, - 0); - - for (row = 0; row < dest_image_length; row++) if (1 != TIFFReadScanline (in, - bitmap->bits + row * bitmap->rowbytes, + bitmap->bits + row * bitmap->row_words, row, 0)) { @@ -435,7 +418,7 @@ boolean process_page (int image, /* range 1 .. n */ for (row = 0; row < rect_height (& bitmap->rect); row++) if (1 != TIFFWriteScanline (tiff_temp, - bitmap->bits + row * bitmap->rowbytes, + bitmap->bits + row * bitmap->row_words, row, 0)) {