bitblt.c

changeset 42
9c85a4cd88a3
parent 35
41804cc569ab
child 43
b80cb5a4282a
     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 +}