bitblt.c

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

author
eric
date
Wed, 02 Jan 2002 16:39:39 +0000
changeset 42
9c85a4cd88a3
parent 35
41804cc569ab
child 43
b80cb5a4282a
permissions
-rw-r--r--

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

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     5 #include "type.h"
     6 #include "bitblt.h"
     9 #define CALC_ROWBYTES(width) (((width) - 1) / 8 + 1)
    12 static const u8 bit_reverse_byte [0x100] =
    13 {
    14   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    15   0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    16   0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    17   0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    18   0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    19   0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    20   0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    21   0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    22   0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    23   0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    24   0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    25   0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    26   0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    27   0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    28   0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    29   0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    30   0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    31   0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    32   0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    33   0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    34   0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    35   0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    36   0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    37   0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    38   0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    39   0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    40   0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    41   0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    42   0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    43   0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    44   0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    45   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
    46 };
    49 static u8 *temp_buffer;
    50 static u32 temp_buffer_size;
    52 static void realloc_temp_buffer (u32 size)
    53 {
    54   if (size <= temp_buffer_size)
    55     return;
    56   temp_buffer = realloc (temp_buffer, size);
    57   if (! temp_buffer)
    58     {
    59       fprintf (stderr, "realloc failed in bitblt library\n");
    60       exit (2);
    61     }
    62   temp_buffer_size = size;
    63 }
    66 static inline u8 pixel_mask (x)
    67 {
    68 #ifdef LSB_LEFT
    69   return (1 << x);
    70 #else
    71   return (1 << (7 - x));
    72 #endif
    73 };
    75 Bitmap *create_bitmap (Rect *rect)
    76 {
    77   Bitmap *bitmap;
    78   u32 width = rect_width (rect);
    79   u32 height = rect_height (rect);
    81   if ((width <= 0) || (height <= 0))
    82     return (NULL);
    84   bitmap = calloc (1, sizeof (Bitmap));
    85   if (! bitmap)
    86     return (NULL);
    87   bitmap->rect = * rect;
    88   bitmap->rowbytes = CALC_ROWBYTES (width);
    89   bitmap->bits = calloc (height * bitmap->rowbytes, 1);
    90   if (! bitmap->bits)
    91     {
    92       free (bitmap);
    93       return (NULL);
    94     }
    95   return (bitmap);
    96 }
    98 void free_bitmap (Bitmap *bitmap)
    99 {
   100   free (bitmap->bits);
   101   free (bitmap);
   102 }
   104 boolean get_pixel (Bitmap *bitmap, Point coord)
   105 {
   106   u8 *p;
   107   if ((coord.x < bitmap->rect.min.x) ||
   108       (coord.x >= bitmap->rect.max.x) ||
   109       (coord.y < bitmap->rect.min.y) ||
   110       (coord.y >= bitmap->rect.max.y))
   111     return (0);
   112   p = bitmap->bits +
   113     (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
   114     (coord.x - bitmap->rect.min.x) / 8;
   115   return ((*p & pixel_mask (coord.x & 7)) != 0);
   116 }
   118 void set_pixel (Bitmap *bitmap, Point coord, boolean value)
   119 {
   120   u8 *p;
   121   if ((coord.x < bitmap->rect.min.x) ||
   122       (coord.x >= bitmap->rect.max.x) ||
   123       (coord.y < bitmap->rect.min.y) ||
   124       (coord.y >= bitmap->rect.max.y))
   125     return;
   126   p = bitmap->bits +
   127     (coord.y - bitmap->rect.min.y) * bitmap->rowbytes +
   128     (coord.x - bitmap->rect.min.x) / 8;
   129   if (value)
   130     *p |= pixel_mask (coord.x & 7);
   131   else
   132     *p &= (0xff ^ pixel_mask (coord.x & 7));
   133 }
   136 /* modifies rect1 to be the intersection of rect1 and rect2;
   137    returns true if intersection is non-null */
   138 static boolean clip_rect (Rect *rect1, Rect *rect2)
   139 {
   140   if (rect1->min.y > rect2->max.y)
   141     goto empty;
   142   if (rect1->min.y < rect2->min.y)
   143     {
   144       if (rect1->max.y < rect2->max.y)
   145 	goto empty;
   146       rect1->min.y = rect2->min.y;
   147     }
   148   if (rect1->max.y > rect2->max.y)
   149     rect1->max.y = rect2->max.y;
   151   if (rect1->min.x > rect2->max.x)
   152     goto empty;
   153   if (rect1->min.x < rect2->min.x)
   154     {
   155       if (rect1->max.x < rect2->max.x)
   156 	goto empty;
   157       rect1->min.x = rect2->min.x;
   158     }
   159   if (rect1->max.x > rect2->max.x)
   160     rect1->max.x = rect2->max.x;
   162  empty:
   163   rect1->min.x = rect1->min.y =
   164     rect1->max.x = rect1->max.y = 0;
   165   return (0);
   166 }
   169 Bitmap *bitblt (Bitmap *src_bitmap,
   170 		Rect   *src_rect,
   171 		Bitmap *dest_bitmap,
   172 		Point  *dest_min,
   173 		int tfn)
   174 {
   175   Point src_point, dest_point;
   177   if (! dest_bitmap)
   178     {
   179       Rect dest_rect = {{ 0, 0 }, { dest_min->x + rect_width (src_rect),
   180 				    dest_min->y + rect_height (src_rect) }};
   181       dest_bitmap = create_bitmap (& dest_rect);
   182       if (! dest_bitmap)
   183 	return (NULL);
   184     }
   186   for (src_point.y = src_rect->min.y;
   187        src_point.y < src_rect->max.y;
   188        src_point.y++)
   189     {
   190       dest_point.y = dest_min->y + src_point.y - src_rect->min.y;
   192       for (src_point.x = src_rect->min.x;
   193 	   src_point.x < src_rect->max.x;
   194 	   src_point.x++)
   195 	{
   196 	  boolean a, b, c;
   198 	  dest_point.x = dest_min->x + src_point.x - src_rect->min.x;
   200 	  a = get_pixel (src_bitmap, src_point);
   201 	  b = get_pixel (dest_bitmap, dest_point);
   202 	  c = (tfn & (1 << (a * 2 + b))) != 0;
   204 	  set_pixel (dest_bitmap, dest_point, c);
   205 	}
   206     }
   207   return (dest_bitmap);
   208 }
   211 /* in-place transformations */
   212 void flip_h (Bitmap *src)
   213 {
   214   u8 *rp;  /* row pointer */
   215   u8 *p1;  /* work src ptr */
   216   u8 *p2;  /* work dest ptr */
   217   u16 d;
   218   s32 y;
   219   int shift;
   221   realloc_temp_buffer (src->rowbytes + 1);
   223   rp = src->bits;
   224   if ((rect_width (& src->rect) & 7) == 0)
   225     {
   226       for (y = src->rect.min.y; y < src->rect.max.y; y++)
   227 	{
   228 	  memcpy (temp_buffer, rp, src->rowbytes);
   229 	  p1 = temp_buffer + src->rowbytes - 1;
   230 	  p2 = rp;
   232 	  while (p1 >= temp_buffer)
   233 	    *(p2++) = bit_reverse_byte [*(p1--)];
   235 	  rp += src->rowbytes;
   236 	}
   237       return;
   238     }
   240   temp_buffer [0] = 0;
   241   shift = 8 - (rect_width (& src->rect) & 7);
   243   for (y = src->rect.min.y; y < src->rect.max.y; y++)
   244     {
   245       memcpy (temp_buffer + 1, rp, src->rowbytes);
   246       p1 = temp_buffer + src->rowbytes;
   247       p2 = rp;
   249       d = *(p1--);
   251       while (p1 >= temp_buffer)
   252 	{
   253 	  d = (d >> 8) | ((*(p1--)) << 8);
   254 	  *(p2++) = bit_reverse_byte [(d >> shift) & 0xff];
   255 	}      
   257       rp += src->rowbytes;
   258     }
   259 }
   261 void flip_v (Bitmap *src)
   262 {
   263   u8 *p1, *p2;
   265   realloc_temp_buffer (src->rowbytes);
   267   p1 = src->bits;
   268   p2 = src->bits + src->rowbytes * (rect_height (& src->rect) - 1);
   269   while (p1 < p2)
   270     {
   271       memcpy (temp_buffer, p1, src->rowbytes);
   272       memcpy (p1, p2, src->rowbytes);
   273       memcpy (p2, temp_buffer, src->rowbytes);
   274       p1 += src->rowbytes;
   275       p2 -= src->rowbytes;
   276     }
   277 }
   279 void rot_180 (Bitmap *src)  /* combination of flip_h and flip_v */
   280 {
   281   flip_h (src);
   282   flip_v (src);
   283 }
   285 /* "in-place" transformations - will allocate new memory and free old */
   286 void transpose (Bitmap *src)
   287 {
   288   u32 new_rowbytes = CALC_ROWBYTES (rect_height (& src->rect));
   289   u8 *new_bits;
   291   new_bits = calloc (1, new_rowbytes * rect_width (& src->rect));
   293   /* $$$ more code needed here */
   294 }
   296 void rot_90 (Bitmap *src)   /* transpose + flip_h */
   297 {
   298   transpose (src);
   299   flip_h (src);
   300 }
   302 void rot_270 (Bitmap *src)  /* transpose + flip_v */
   303 {
   304   transpose (src);
   305   flip_v (src);
   306 }