started work on bitblt optimization - split rotate functions from bitblt.

Wed, 02 Jan 2002 16:39:39 +0000

author
eric
date
Wed, 02 Jan 2002 16:39:39 +0000
changeset 42
9c85a4cd88a3
parent 41
2350a4b7393c
child 43
b80cb5a4282a

started work on bitblt optimization - split rotate functions from bitblt.

bitblt.c file | annotate | diff | revisions
bitblt.h file | annotate | diff | revisions
t2p.c file | annotate | diff | revisions
tumble.c file | annotate | diff | revisions
     1.1 --- a/bitblt.c	Wed Jan 02 16:39:20 2002 +0000
     1.2 +++ b/bitblt.c	Wed Jan 02 16:39:39 2002 +0000
     1.3 @@ -1,8 +1,68 @@
     1.4 +#include <stdio.h>
     1.5  #include <stdlib.h>
     1.6 +#include <string.h>
     1.7  
     1.8  #include "type.h"
     1.9  #include "bitblt.h"
    1.10  
    1.11 +
    1.12 +#define CALC_ROWBYTES(width) (((width) - 1) / 8 + 1)
    1.13 +
    1.14 +
    1.15 +static const u8 bit_reverse_byte [0x100] =
    1.16 +{
    1.17 +  0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    1.18 +  0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    1.19 +  0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    1.20 +  0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    1.21 +  0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    1.22 +  0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    1.23 +  0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    1.24 +  0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    1.25 +  0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    1.26 +  0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    1.27 +  0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    1.28 +  0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    1.29 +  0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    1.30 +  0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    1.31 +  0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    1.32 +  0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    1.33 +  0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    1.34 +  0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    1.35 +  0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    1.36 +  0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    1.37 +  0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    1.38 +  0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    1.39 +  0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    1.40 +  0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    1.41 +  0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    1.42 +  0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    1.43 +  0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    1.44 +  0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    1.45 +  0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    1.46 +  0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    1.47 +  0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    1.48 +  0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
    1.49 +};
    1.50 +
    1.51 +
    1.52 +static u8 *temp_buffer;
    1.53 +static u32 temp_buffer_size;
    1.54 +
    1.55 +static void realloc_temp_buffer (u32 size)
    1.56 +{
    1.57 +  if (size <= temp_buffer_size)
    1.58 +    return;
    1.59 +  temp_buffer = realloc (temp_buffer, size);
    1.60 +  if (! temp_buffer)
    1.61 +    {
    1.62 +      fprintf (stderr, "realloc failed in bitblt library\n");
    1.63 +      exit (2);
    1.64 +    }
    1.65 +  temp_buffer_size = size;
    1.66 +}
    1.67 +
    1.68 +
    1.69  static inline u8 pixel_mask (x)
    1.70  {
    1.71  #ifdef LSB_LEFT
    1.72 @@ -10,21 +70,13 @@
    1.73  #else
    1.74    return (1 << (7 - x));
    1.75  #endif
    1.76 -}
    1.77 -
    1.78 -static inline s32 rect_width (Rect r)
    1.79 -{
    1.80 -  return (r.lower_right.x - r.upper_left.x);
    1.81 -}
    1.82 +};
    1.83  
    1.84 -static inline s32 rect_height (Rect r)
    1.85 -{
    1.86 -  return (r.lower_right.y - r.upper_left.y);
    1.87 -}
    1.88 -
    1.89 -Bitmap *create_bitmap (s32 width, s32 height)
    1.90 +Bitmap *create_bitmap (Rect *rect)
    1.91  {
    1.92    Bitmap *bitmap;
    1.93 +  u32 width = rect_width (rect);
    1.94 +  u32 height = rect_height (rect);
    1.95  
    1.96    if ((width <= 0) || (height <= 0))
    1.97      return (NULL);
    1.98 @@ -32,9 +84,8 @@
    1.99    bitmap = calloc (1, sizeof (Bitmap));
   1.100    if (! bitmap)
   1.101      return (NULL);
   1.102 -  bitmap->width = width;
   1.103 -  bitmap->height = height;
   1.104 -  bitmap->rowbytes = (width - 1) / 8 + 1;
   1.105 +  bitmap->rect = * rect;
   1.106 +  bitmap->rowbytes = CALC_ROWBYTES (width);
   1.107    bitmap->bits = calloc (height * bitmap->rowbytes, 1);
   1.108    if (! bitmap->bits)
   1.109      {
   1.110 @@ -53,20 +104,28 @@
   1.111  boolean get_pixel (Bitmap *bitmap, Point coord)
   1.112  {
   1.113    u8 *p;
   1.114 -  if ((coord.x < 0) || (coord.y < 0) ||
   1.115 -      (coord.x >= bitmap->width) || (coord.y >= bitmap->height))
   1.116 +  if ((coord.x < bitmap->rect.min.x) ||
   1.117 +      (coord.x >= bitmap->rect.max.x) ||
   1.118 +      (coord.y < bitmap->rect.min.y) ||
   1.119 +      (coord.y >= bitmap->rect.max.y))
   1.120      return (0);
   1.121 -  p = bitmap->bits + coord.y * bitmap->rowbytes + coord.x / 8;
   1.122 +  p = bitmap->bits +
   1.123 +    (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
   1.124 +    (coord.x - bitmap->rect.min.x) / 8;
   1.125    return ((*p & pixel_mask (coord.x & 7)) != 0);
   1.126  }
   1.127  
   1.128  void set_pixel (Bitmap *bitmap, Point coord, boolean value)
   1.129  {
   1.130    u8 *p;
   1.131 -  if ((coord.x < 0) || (coord.y < 0) ||
   1.132 -      (coord.x >= bitmap->width) || (coord.y >= bitmap->height))
   1.133 +  if ((coord.x < bitmap->rect.min.x) ||
   1.134 +      (coord.x >= bitmap->rect.max.x) ||
   1.135 +      (coord.y < bitmap->rect.min.y) ||
   1.136 +      (coord.y >= bitmap->rect.max.y))
   1.137      return;
   1.138 -  p = bitmap->bits + coord.y * bitmap->rowbytes + coord.x / 8;
   1.139 +  p = bitmap->bits +
   1.140 +    (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
   1.141 +    (coord.x - bitmap->rect.min.x) / 8;
   1.142    if (value)
   1.143      *p |= pixel_mask (coord.x & 7);
   1.144    else
   1.145 @@ -74,62 +133,69 @@
   1.146  }
   1.147  
   1.148  
   1.149 +/* modifies rect1 to be the intersection of rect1 and rect2;
   1.150 +   returns true if intersection is non-null */
   1.151 +static boolean clip_rect (Rect *rect1, Rect *rect2)
   1.152 +{
   1.153 +  if (rect1->min.y > rect2->max.y)
   1.154 +    goto empty;
   1.155 +  if (rect1->min.y < rect2->min.y)
   1.156 +    {
   1.157 +      if (rect1->max.y < rect2->max.y)
   1.158 +	goto empty;
   1.159 +      rect1->min.y = rect2->min.y;
   1.160 +    }
   1.161 +  if (rect1->max.y > rect2->max.y)
   1.162 +    rect1->max.y = rect2->max.y;
   1.163 +
   1.164 +  if (rect1->min.x > rect2->max.x)
   1.165 +    goto empty;
   1.166 +  if (rect1->min.x < rect2->min.x)
   1.167 +    {
   1.168 +      if (rect1->max.x < rect2->max.x)
   1.169 +	goto empty;
   1.170 +      rect1->min.x = rect2->min.x;
   1.171 +    }
   1.172 +  if (rect1->max.x > rect2->max.x)
   1.173 +    rect1->max.x = rect2->max.x;
   1.174 +
   1.175 + empty:
   1.176 +  rect1->min.x = rect1->min.y =
   1.177 +    rect1->max.x = rect1->max.y = 0;
   1.178 +  return (0);
   1.179 +}
   1.180 +
   1.181 +
   1.182  Bitmap *bitblt (Bitmap *src_bitmap,
   1.183 -		Rect src_rect,
   1.184 +		Rect   *src_rect,
   1.185  		Bitmap *dest_bitmap,
   1.186 -		Point dest_upper_left,
   1.187 -		int scan,
   1.188 +		Point  *dest_min,
   1.189  		int tfn)
   1.190  {
   1.191    Point src_point, dest_point;
   1.192  
   1.193    if (! dest_bitmap)
   1.194      {
   1.195 -      if (scan & TRANSPOSE)
   1.196 -	dest_bitmap = create_bitmap (dest_upper_left.x + rect_height (src_rect),
   1.197 -				     dest_upper_left.y + rect_width (src_rect));
   1.198 -      else
   1.199 -	dest_bitmap = create_bitmap (dest_upper_left.x + rect_width (src_rect),
   1.200 -				     dest_upper_left.y + rect_height (src_rect));
   1.201 +      Rect dest_rect = {{ 0, 0 }, { dest_min->x + rect_width (src_rect),
   1.202 +				    dest_min->y + rect_height (src_rect) }};
   1.203 +      dest_bitmap = create_bitmap (& dest_rect);
   1.204        if (! dest_bitmap)
   1.205  	return (NULL);
   1.206      }
   1.207  
   1.208 -  for (src_point.y = src_rect.upper_left.y;
   1.209 -       src_point.y < src_rect.lower_right.y;
   1.210 +  for (src_point.y = src_rect->min.y;
   1.211 +       src_point.y < src_rect->max.y;
   1.212         src_point.y++)
   1.213      {
   1.214 -      for (src_point.x = src_rect.upper_left.x;
   1.215 -	   src_point.x < src_rect.lower_right.x;
   1.216 +      dest_point.y = dest_min->y + src_point.y - src_rect->min.y;
   1.217 +
   1.218 +      for (src_point.x = src_rect->min.x;
   1.219 +	   src_point.x < src_rect->max.x;
   1.220  	   src_point.x++)
   1.221  	{
   1.222  	  boolean a, b, c;
   1.223  
   1.224 -	  if (scan & TRANSPOSE)
   1.225 -	    {
   1.226 -	      dest_point.x = src_point.y - src_rect.upper_left.y;
   1.227 -	      dest_point.y = src_point.x - src_rect.upper_left.x;
   1.228 -
   1.229 -	      if (scan & FLIP_H)
   1.230 -		dest_point.x = (rect_height (src_rect) - 1) - dest_point.x;
   1.231 -
   1.232 -	      if (scan & FLIP_V)
   1.233 -		dest_point.y = (rect_width (src_rect) - 1) - dest_point.y;
   1.234 -	    }
   1.235 -	  else
   1.236 -	    {
   1.237 -	      dest_point.x = src_point.x - src_rect.upper_left.x;
   1.238 -	      dest_point.y = src_point.y - src_rect.upper_left.y;
   1.239 -
   1.240 -	      if (scan & FLIP_H)
   1.241 -		dest_point.x = (rect_width (src_rect) - 1) - dest_point.x;
   1.242 -
   1.243 -	      if (scan & FLIP_V)
   1.244 -		dest_point.y = (rect_height (src_rect) - 1) - dest_point.y;
   1.245 -	    }
   1.246 -
   1.247 -	  dest_point.x += dest_upper_left.x;
   1.248 -	  dest_point.y += dest_upper_left.y;
   1.249 +	  dest_point.x = dest_min->x + src_point.x - src_rect->min.x;
   1.250  
   1.251  	  a = get_pixel (src_bitmap, src_point);
   1.252  	  b = get_pixel (dest_bitmap, dest_point);
   1.253 @@ -140,3 +206,101 @@
   1.254      }
   1.255    return (dest_bitmap);
   1.256  }
   1.257 +
   1.258 +
   1.259 +/* in-place transformations */
   1.260 +void flip_h (Bitmap *src)
   1.261 +{
   1.262 +  u8 *rp;  /* row pointer */
   1.263 +  u8 *p1;  /* work src ptr */
   1.264 +  u8 *p2;  /* work dest ptr */
   1.265 +  u16 d;
   1.266 +  s32 y;
   1.267 +  int shift;
   1.268 +
   1.269 +  realloc_temp_buffer (src->rowbytes + 1);
   1.270 +
   1.271 +  rp = src->bits;
   1.272 +  if ((rect_width (& src->rect) & 7) == 0)
   1.273 +    {
   1.274 +      for (y = src->rect.min.y; y < src->rect.max.y; y++)
   1.275 +	{
   1.276 +	  memcpy (temp_buffer, rp, src->rowbytes);
   1.277 +	  p1 = temp_buffer + src->rowbytes - 1;
   1.278 +	  p2 = rp;
   1.279 +
   1.280 +	  while (p1 >= temp_buffer)
   1.281 +	    *(p2++) = bit_reverse_byte [*(p1--)];
   1.282 +      
   1.283 +	  rp += src->rowbytes;
   1.284 +	}
   1.285 +      return;
   1.286 +    }
   1.287 +
   1.288 +  temp_buffer [0] = 0;
   1.289 +  shift = 8 - (rect_width (& src->rect) & 7);
   1.290 +
   1.291 +  for (y = src->rect.min.y; y < src->rect.max.y; y++)
   1.292 +    {
   1.293 +      memcpy (temp_buffer + 1, rp, src->rowbytes);
   1.294 +      p1 = temp_buffer + src->rowbytes;
   1.295 +      p2 = rp;
   1.296 +
   1.297 +      d = *(p1--);
   1.298 +
   1.299 +      while (p1 >= temp_buffer)
   1.300 +	{
   1.301 +	  d = (d >> 8) | ((*(p1--)) << 8);
   1.302 +	  *(p2++) = bit_reverse_byte [(d >> shift) & 0xff];
   1.303 +	}      
   1.304 +
   1.305 +      rp += src->rowbytes;
   1.306 +    }
   1.307 +}
   1.308 +
   1.309 +void flip_v (Bitmap *src)
   1.310 +{
   1.311 +  u8 *p1, *p2;
   1.312 +
   1.313 +  realloc_temp_buffer (src->rowbytes);
   1.314 +
   1.315 +  p1 = src->bits;
   1.316 +  p2 = src->bits + src->rowbytes * (rect_height (& src->rect) - 1);
   1.317 +  while (p1 < p2)
   1.318 +    {
   1.319 +      memcpy (temp_buffer, p1, src->rowbytes);
   1.320 +      memcpy (p1, p2, src->rowbytes);
   1.321 +      memcpy (p2, temp_buffer, src->rowbytes);
   1.322 +      p1 += src->rowbytes;
   1.323 +      p2 -= src->rowbytes;
   1.324 +    }
   1.325 +}
   1.326 +
   1.327 +void rot_180 (Bitmap *src)  /* combination of flip_h and flip_v */
   1.328 +{
   1.329 +  flip_h (src);
   1.330 +  flip_v (src);
   1.331 +}
   1.332 +
   1.333 +/* "in-place" transformations - will allocate new memory and free old */
   1.334 +void transpose (Bitmap *src)
   1.335 +{
   1.336 +  u32 new_rowbytes = CALC_ROWBYTES (rect_height (& src->rect));
   1.337 +  u8 *new_bits;
   1.338 +
   1.339 +  new_bits = calloc (1, new_rowbytes * rect_width (& src->rect));
   1.340 +
   1.341 +  /* $$$ more code needed here */
   1.342 +}
   1.343 +
   1.344 +void rot_90 (Bitmap *src)   /* transpose + flip_h */
   1.345 +{
   1.346 +  transpose (src);
   1.347 +  flip_h (src);
   1.348 +}
   1.349 +
   1.350 +void rot_270 (Bitmap *src)  /* transpose + flip_v */
   1.351 +{
   1.352 +  transpose (src);
   1.353 +  flip_v (src);
   1.354 +}
     2.1 --- a/bitblt.h	Wed Jan 02 16:39:20 2002 +0000
     2.2 +++ b/bitblt.h	Wed Jan 02 16:39:39 2002 +0000
     2.3 @@ -6,15 +6,24 @@
     2.4  
     2.5  typedef struct Rect
     2.6  {
     2.7 -  Point upper_left;
     2.8 -  Point lower_right;
     2.9 +  Point min;
    2.10 +  Point max;
    2.11  } Rect;
    2.12  
    2.13 +static inline s32 rect_width (Rect *r)
    2.14 +{
    2.15 +  return (r->max.x - r->min.x);
    2.16 +}
    2.17 +
    2.18 +static inline s32 rect_height (Rect *r)
    2.19 +{
    2.20 +  return (r->max.y - r->min.y);
    2.21 +}
    2.22 +
    2.23  typedef struct Bitmap
    2.24  {
    2.25    u8 *bits;
    2.26 -  s32 width;
    2.27 -  s32 height;
    2.28 +  Rect rect;
    2.29    u32 rowbytes;
    2.30  } Bitmap;
    2.31  
    2.32 @@ -25,24 +34,28 @@
    2.33  #define TF_XOR 0x6
    2.34  
    2.35  
    2.36 -#define FLIP_H    0x1
    2.37 -#define FLIP_V    0x2
    2.38 -#define TRANSPOSE 0x4
    2.39 +Bitmap *create_bitmap (Rect *rect);
    2.40 +void free_bitmap (Bitmap *bitmap);
    2.41  
    2.42 -#define ROT_0     0x0
    2.43 -#define ROT_90    (TRANSPOSE + FLIP_H)
    2.44 -#define ROT_180   (FLIP_H + FLIP_V)
    2.45 -#define ROT_270   (TRANSPOSE + FLIP_V)
    2.46 -
    2.47 -
    2.48 -Bitmap *create_bitmap (s32 width, s32 height);
    2.49 -void free_bitmap (Bitmap *bitmap);
    2.50  boolean get_pixel (Bitmap *bitmap, Point coord);
    2.51  void set_pixel (Bitmap *bitmap, Point coord, boolean value);
    2.52  
    2.53 +
    2.54  Bitmap *bitblt (Bitmap *src_bitmap,
    2.55 -		Rect src_rect,
    2.56 +		Rect   *src_rect,
    2.57  		Bitmap *dest_bitmap,
    2.58 -		Point dest_upper_left,
    2.59 -		int scan,
    2.60 +		Point  *dest_min,
    2.61  		int tfn);
    2.62 +
    2.63 +
    2.64 +/* in-place transformations */
    2.65 +void flip_h (Bitmap *src);
    2.66 +void flip_v (Bitmap *src);
    2.67 +
    2.68 +void rot_180 (Bitmap *src);  /* combination of flip_h and flip_v */
    2.69 +
    2.70 +/* "in-place" transformations - will allocate new memory and free old */
    2.71 +void transpose (Bitmap *src);
    2.72 +
    2.73 +void rot_90 (Bitmap *src);   /* transpose + flip_h */
    2.74 +void rot_270 (Bitmap *src);  /* transpose + flip_v */
     3.1 --- a/t2p.c	Wed Jan 02 16:39:20 2002 +0000
     3.2 +++ b/t2p.c	Wed Jan 02 16:39:39 2002 +0000
     3.3 @@ -5,7 +5,7 @@
     3.4   *           encoding.
     3.5   *
     3.6   * Main program
     3.7 - * $Id: t2p.c,v 1.13 2002/01/02 02:18:13 eric Exp $
     3.8 + * $Id: t2p.c,v 1.14 2002/01/02 08:39:39 eric Exp $
     3.9   * Copyright 2001 Eric Smith <eric@brouhaha.com>
    3.10   *
    3.11   * This program is free software; you can redistribute it and/or modify
    3.12 @@ -179,53 +179,46 @@
    3.13  }
    3.14  
    3.15  
    3.16 -static Bitmap *rotate_bitmap (Bitmap *src,
    3.17 +/* frees original! */
    3.18 +static Bitmap *resize_bitmap (Bitmap *src,
    3.19  			      float x_resolution,
    3.20  			      float y_resolution,
    3.21  			      input_attributes_t input_attributes)
    3.22  {
    3.23    Rect src_rect;
    3.24 -  Point dest_upper_left;
    3.25 -  int scan;
    3.26 +  Point dest_min;
    3.27 +  Bitmap *dest;
    3.28  
    3.29 -  if (input_attributes.has_page_size)
    3.30 -    {
    3.31 -      int width_pixels = input_attributes.page_size.width * x_resolution;
    3.32 -      int height_pixels = input_attributes.page_size.height * y_resolution;
    3.33 +  int width_pixels = input_attributes.page_size.width * x_resolution;
    3.34 +  int height_pixels = input_attributes.page_size.height * y_resolution;
    3.35 +
    3.36 +  src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
    3.37 +  src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
    3.38 +  src_rect.max.x = src_rect.min.x + width_pixels;
    3.39 +  src_rect.max.y = src_rect.min.y + height_pixels;
    3.40  
    3.41 -      src_rect.upper_left.x = (src->width - width_pixels) / 2;
    3.42 -      src_rect.upper_left.y = (src->height - height_pixels) / 2;
    3.43 -      src_rect.lower_right.x = src_rect.upper_left.x + width_pixels;
    3.44 -      src_rect.lower_right.y = src_rect.upper_left.y + height_pixels;
    3.45 -    }
    3.46 -  else
    3.47 -    {
    3.48 -      src_rect.upper_left.x = 0;
    3.49 -      src_rect.upper_left.y = 0;
    3.50 -      src_rect.lower_right.x = src->width;
    3.51 -      src_rect.lower_right.y = src->height;
    3.52 -    }
    3.53 +  dest_min.x = 0;
    3.54 +  dest_min.y = 0;
    3.55  
    3.56 -  dest_upper_left.x = 0;
    3.57 -  dest_upper_left.y = 0;
    3.58 +  dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC);
    3.59 +  free_bitmap (src);
    3.60 +  return (dest);
    3.61 +}
    3.62  
    3.63 +
    3.64 +/* "in place" rotation */
    3.65 +static void rotate_bitmap (Bitmap *src,
    3.66 +			   input_attributes_t input_attributes)
    3.67 +{
    3.68    switch (input_attributes.rotation)
    3.69      {
    3.70 -    case 0: scan = ROT_0; break;
    3.71 -    case 90: scan = ROT_90; break;
    3.72 -    case 180: scan = ROT_180; break;
    3.73 -    case 270: scan = ROT_270; break;
    3.74 +    case 0: break;
    3.75 +    case 90: rot_90 (src); break;
    3.76 +    case 180: rot_180 (src); break;
    3.77 +    case 270: rot_270 (src); break;
    3.78      default:
    3.79        fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
    3.80 -      return (NULL);
    3.81      }
    3.82 -
    3.83 -  return (bitblt (src,
    3.84 -		  src_rect,
    3.85 -		  NULL,  /* dest_bitmap */
    3.86 -		  dest_upper_left,
    3.87 -		  scan,
    3.88 -		  TF_SRC));
    3.89  }
    3.90  
    3.91  
    3.92 @@ -256,8 +249,9 @@
    3.93    int width_points, height_points;  /* really 1/72 inch units rather than
    3.94  				       points */
    3.95  
    3.96 -  Bitmap *src_bitmap;
    3.97 -  Bitmap *dest_bitmap;
    3.98 +  Rect rect;
    3.99 +  Bitmap *bitmap;
   3.100 +
   3.101    int row;
   3.102  
   3.103    panda_page *page;
   3.104 @@ -366,29 +360,35 @@
   3.105  
   3.106    scanline_size = TIFFScanlineSize (in);
   3.107  
   3.108 -  src_bitmap = create_bitmap (image_width, image_length);
   3.109 -  if (! src_bitmap)
   3.110 +  rect.min.x = 0;
   3.111 +  rect.min.y = 0;
   3.112 +  rect.max.x = image_width;
   3.113 +  rect.max.y = image_length;
   3.114 +
   3.115 +  bitmap = create_bitmap (& rect);
   3.116 +
   3.117 +  if (! bitmap)
   3.118      {
   3.119        fprintf (stderr, "can't allocate bitmap\n");
   3.120        goto fail;
   3.121      }
   3.122  
   3.123 -  if (src_bitmap->rowbytes != scanline_size)
   3.124 +  if (bitmap->rowbytes != scanline_size)
   3.125      {
   3.126        printf ("image_width %d\n", image_width);
   3.127 -      printf ("rowbytes %d\n", src_bitmap->rowbytes);
   3.128 +      printf ("rowbytes %d\n", bitmap->rowbytes);
   3.129        printf ("TIFFScanlineSize %d\n", scanline_size);
   3.130      }
   3.131  
   3.132    for (row = 0; row < image_length; row++)
   3.133      TIFFReadScanline (in,
   3.134 -		      src_bitmap->bits + row * src_bitmap->rowbytes,
   3.135 +		      bitmap->bits + row * bitmap->rowbytes,
   3.136  		      row,
   3.137  		      0);
   3.138  
   3.139    for (row = 0; row < dest_image_length; row++)
   3.140      if (1 != TIFFReadScanline (in,
   3.141 -			       src_bitmap->bits + row * src_bitmap->rowbytes,
   3.142 +			       bitmap->bits + row * bitmap->rowbytes,
   3.143  			       row,
   3.144  			       0))
   3.145        {
   3.146 @@ -396,15 +396,13 @@
   3.147  	goto fail;
   3.148        }
   3.149  
   3.150 -  dest_bitmap = rotate_bitmap (src_bitmap,
   3.151 -			       x_resolution,
   3.152 -			       y_resolution,
   3.153 -			       input_attributes);
   3.154 -  if (! dest_bitmap)
   3.155 -    {
   3.156 -      fprintf (stderr, "can't allocate bitmap\n");
   3.157 -      goto fail;
   3.158 -    }
   3.159 +  bitmap = resize_bitmap (bitmap,
   3.160 +			      x_resolution,
   3.161 +			      y_resolution,
   3.162 +			      input_attributes);
   3.163 +
   3.164 +  rotate_bitmap (bitmap,
   3.165 +		 input_attributes);
   3.166  
   3.167    tiff_temp_fd = mkstemp (tiff_temp_fn);
   3.168    if (tiff_temp_fd < 0)
   3.169 @@ -420,11 +418,11 @@
   3.170        goto fail;
   3.171      }
   3.172  
   3.173 -  TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, dest_bitmap->height);
   3.174 -  TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, dest_bitmap->width);
   3.175 +  TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, rect_height (& bitmap->rect));
   3.176 +  TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, rect_width (& bitmap->rect));
   3.177    TIFFSetField (tiff_temp, TIFFTAG_PLANARCONFIG, planar_config);
   3.178  
   3.179 -  TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, dest_bitmap->height);
   3.180 +  TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, rect_height (& bitmap->rect));
   3.181  
   3.182    TIFFSetField (tiff_temp, TIFFTAG_RESOLUTIONUNIT, resolution_unit);
   3.183    TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, dest_x_resolution);
   3.184 @@ -435,9 +433,9 @@
   3.185    TIFFSetField (tiff_temp, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
   3.186    TIFFSetField (tiff_temp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
   3.187  
   3.188 -  for (row = 0; row < dest_bitmap->height; row++)
   3.189 +  for (row = 0; row < rect_height (& bitmap->rect); row++)
   3.190      if (1 != TIFFWriteScanline (tiff_temp,
   3.191 -				dest_bitmap->bits + row * dest_bitmap->rowbytes,
   3.192 +				bitmap->bits + row * bitmap->rowbytes,
   3.193  				row,
   3.194  				0))
   3.195        {
   3.196 @@ -447,11 +445,10 @@
   3.197  
   3.198    TIFFClose (tiff_temp);
   3.199  
   3.200 -  width_points = (dest_bitmap->width / dest_x_resolution) * POINTS_PER_INCH;
   3.201 -  height_points = (dest_bitmap->height / dest_y_resolution) * POINTS_PER_INCH;
   3.202 +  width_points = (rect_width (& bitmap->rect) / dest_x_resolution) * POINTS_PER_INCH;
   3.203 +  height_points = (rect_height (& bitmap->rect) / dest_y_resolution) * POINTS_PER_INCH;
   3.204  
   3.205 -  free_bitmap (dest_bitmap);
   3.206 -  free_bitmap (src_bitmap);
   3.207 +  free_bitmap (bitmap);
   3.208  
   3.209    if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS))
   3.210      {
     4.1 --- a/tumble.c	Wed Jan 02 16:39:20 2002 +0000
     4.2 +++ b/tumble.c	Wed Jan 02 16:39:39 2002 +0000
     4.3 @@ -5,7 +5,7 @@
     4.4   *           encoding.
     4.5   *
     4.6   * Main program
     4.7 - * $Id: tumble.c,v 1.13 2002/01/02 02:18:13 eric Exp $
     4.8 + * $Id: tumble.c,v 1.14 2002/01/02 08:39:39 eric Exp $
     4.9   * Copyright 2001 Eric Smith <eric@brouhaha.com>
    4.10   *
    4.11   * This program is free software; you can redistribute it and/or modify
    4.12 @@ -179,53 +179,46 @@
    4.13  }
    4.14  
    4.15  
    4.16 -static Bitmap *rotate_bitmap (Bitmap *src,
    4.17 +/* frees original! */
    4.18 +static Bitmap *resize_bitmap (Bitmap *src,
    4.19  			      float x_resolution,
    4.20  			      float y_resolution,
    4.21  			      input_attributes_t input_attributes)
    4.22  {
    4.23    Rect src_rect;
    4.24 -  Point dest_upper_left;
    4.25 -  int scan;
    4.26 +  Point dest_min;
    4.27 +  Bitmap *dest;
    4.28  
    4.29 -  if (input_attributes.has_page_size)
    4.30 -    {
    4.31 -      int width_pixels = input_attributes.page_size.width * x_resolution;
    4.32 -      int height_pixels = input_attributes.page_size.height * y_resolution;
    4.33 +  int width_pixels = input_attributes.page_size.width * x_resolution;
    4.34 +  int height_pixels = input_attributes.page_size.height * y_resolution;
    4.35 +
    4.36 +  src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
    4.37 +  src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
    4.38 +  src_rect.max.x = src_rect.min.x + width_pixels;
    4.39 +  src_rect.max.y = src_rect.min.y + height_pixels;
    4.40  
    4.41 -      src_rect.upper_left.x = (src->width - width_pixels) / 2;
    4.42 -      src_rect.upper_left.y = (src->height - height_pixels) / 2;
    4.43 -      src_rect.lower_right.x = src_rect.upper_left.x + width_pixels;
    4.44 -      src_rect.lower_right.y = src_rect.upper_left.y + height_pixels;
    4.45 -    }
    4.46 -  else
    4.47 -    {
    4.48 -      src_rect.upper_left.x = 0;
    4.49 -      src_rect.upper_left.y = 0;
    4.50 -      src_rect.lower_right.x = src->width;
    4.51 -      src_rect.lower_right.y = src->height;
    4.52 -    }
    4.53 +  dest_min.x = 0;
    4.54 +  dest_min.y = 0;
    4.55  
    4.56 -  dest_upper_left.x = 0;
    4.57 -  dest_upper_left.y = 0;
    4.58 +  dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC);
    4.59 +  free_bitmap (src);
    4.60 +  return (dest);
    4.61 +}
    4.62  
    4.63 +
    4.64 +/* "in place" rotation */
    4.65 +static void rotate_bitmap (Bitmap *src,
    4.66 +			   input_attributes_t input_attributes)
    4.67 +{
    4.68    switch (input_attributes.rotation)
    4.69      {
    4.70 -    case 0: scan = ROT_0; break;
    4.71 -    case 90: scan = ROT_90; break;
    4.72 -    case 180: scan = ROT_180; break;
    4.73 -    case 270: scan = ROT_270; break;
    4.74 +    case 0: break;
    4.75 +    case 90: rot_90 (src); break;
    4.76 +    case 180: rot_180 (src); break;
    4.77 +    case 270: rot_270 (src); break;
    4.78      default:
    4.79        fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
    4.80 -      return (NULL);
    4.81      }
    4.82 -
    4.83 -  return (bitblt (src,
    4.84 -		  src_rect,
    4.85 -		  NULL,  /* dest_bitmap */
    4.86 -		  dest_upper_left,
    4.87 -		  scan,
    4.88 -		  TF_SRC));
    4.89  }
    4.90  
    4.91  
    4.92 @@ -256,8 +249,9 @@
    4.93    int width_points, height_points;  /* really 1/72 inch units rather than
    4.94  				       points */
    4.95  
    4.96 -  Bitmap *src_bitmap;
    4.97 -  Bitmap *dest_bitmap;
    4.98 +  Rect rect;
    4.99 +  Bitmap *bitmap;
   4.100 +
   4.101    int row;
   4.102  
   4.103    panda_page *page;
   4.104 @@ -366,29 +360,35 @@
   4.105  
   4.106    scanline_size = TIFFScanlineSize (in);
   4.107  
   4.108 -  src_bitmap = create_bitmap (image_width, image_length);
   4.109 -  if (! src_bitmap)
   4.110 +  rect.min.x = 0;
   4.111 +  rect.min.y = 0;
   4.112 +  rect.max.x = image_width;
   4.113 +  rect.max.y = image_length;
   4.114 +
   4.115 +  bitmap = create_bitmap (& rect);
   4.116 +
   4.117 +  if (! bitmap)
   4.118      {
   4.119        fprintf (stderr, "can't allocate bitmap\n");
   4.120        goto fail;
   4.121      }
   4.122  
   4.123 -  if (src_bitmap->rowbytes != scanline_size)
   4.124 +  if (bitmap->rowbytes != scanline_size)
   4.125      {
   4.126        printf ("image_width %d\n", image_width);
   4.127 -      printf ("rowbytes %d\n", src_bitmap->rowbytes);
   4.128 +      printf ("rowbytes %d\n", bitmap->rowbytes);
   4.129        printf ("TIFFScanlineSize %d\n", scanline_size);
   4.130      }
   4.131  
   4.132    for (row = 0; row < image_length; row++)
   4.133      TIFFReadScanline (in,
   4.134 -		      src_bitmap->bits + row * src_bitmap->rowbytes,
   4.135 +		      bitmap->bits + row * bitmap->rowbytes,
   4.136  		      row,
   4.137  		      0);
   4.138  
   4.139    for (row = 0; row < dest_image_length; row++)
   4.140      if (1 != TIFFReadScanline (in,
   4.141 -			       src_bitmap->bits + row * src_bitmap->rowbytes,
   4.142 +			       bitmap->bits + row * bitmap->rowbytes,
   4.143  			       row,
   4.144  			       0))
   4.145        {
   4.146 @@ -396,15 +396,13 @@
   4.147  	goto fail;
   4.148        }
   4.149  
   4.150 -  dest_bitmap = rotate_bitmap (src_bitmap,
   4.151 -			       x_resolution,
   4.152 -			       y_resolution,
   4.153 -			       input_attributes);
   4.154 -  if (! dest_bitmap)
   4.155 -    {
   4.156 -      fprintf (stderr, "can't allocate bitmap\n");
   4.157 -      goto fail;
   4.158 -    }
   4.159 +  bitmap = resize_bitmap (bitmap,
   4.160 +			      x_resolution,
   4.161 +			      y_resolution,
   4.162 +			      input_attributes);
   4.163 +
   4.164 +  rotate_bitmap (bitmap,
   4.165 +		 input_attributes);
   4.166  
   4.167    tiff_temp_fd = mkstemp (tiff_temp_fn);
   4.168    if (tiff_temp_fd < 0)
   4.169 @@ -420,11 +418,11 @@
   4.170        goto fail;
   4.171      }
   4.172  
   4.173 -  TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, dest_bitmap->height);
   4.174 -  TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, dest_bitmap->width);
   4.175 +  TIFFSetField (tiff_temp, TIFFTAG_IMAGELENGTH, rect_height (& bitmap->rect));
   4.176 +  TIFFSetField (tiff_temp, TIFFTAG_IMAGEWIDTH, rect_width (& bitmap->rect));
   4.177    TIFFSetField (tiff_temp, TIFFTAG_PLANARCONFIG, planar_config);
   4.178  
   4.179 -  TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, dest_bitmap->height);
   4.180 +  TIFFSetField (tiff_temp, TIFFTAG_ROWSPERSTRIP, rect_height (& bitmap->rect));
   4.181  
   4.182    TIFFSetField (tiff_temp, TIFFTAG_RESOLUTIONUNIT, resolution_unit);
   4.183    TIFFSetField (tiff_temp, TIFFTAG_XRESOLUTION, dest_x_resolution);
   4.184 @@ -435,9 +433,9 @@
   4.185    TIFFSetField (tiff_temp, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
   4.186    TIFFSetField (tiff_temp, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
   4.187  
   4.188 -  for (row = 0; row < dest_bitmap->height; row++)
   4.189 +  for (row = 0; row < rect_height (& bitmap->rect); row++)
   4.190      if (1 != TIFFWriteScanline (tiff_temp,
   4.191 -				dest_bitmap->bits + row * dest_bitmap->rowbytes,
   4.192 +				bitmap->bits + row * bitmap->rowbytes,
   4.193  				row,
   4.194  				0))
   4.195        {
   4.196 @@ -447,11 +445,10 @@
   4.197  
   4.198    TIFFClose (tiff_temp);
   4.199  
   4.200 -  width_points = (dest_bitmap->width / dest_x_resolution) * POINTS_PER_INCH;
   4.201 -  height_points = (dest_bitmap->height / dest_y_resolution) * POINTS_PER_INCH;
   4.202 +  width_points = (rect_width (& bitmap->rect) / dest_x_resolution) * POINTS_PER_INCH;
   4.203 +  height_points = (rect_height (& bitmap->rect) / dest_y_resolution) * POINTS_PER_INCH;
   4.204  
   4.205 -  free_bitmap (dest_bitmap);
   4.206 -  free_bitmap (src_bitmap);
   4.207 +  free_bitmap (bitmap);
   4.208  
   4.209    if ((height_points > PAGE_MAX_POINTS) || (width_points > PAGE_MAX_POINTS))
   4.210      {