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