pixops.c

来自「linux下电话本所依赖的一些图形库」· C语言 代码 · 共 1,615 行 · 第 1/3 页

C
1,615
字号
				guchar **src, int src_channels, gboolean src_has_alpha,				int x_init, int x_step, int src_width,				int check_size, guint32 color1, guint32 color2){  guint32 mmx_weights[16][8];  int j;  for (j=0; j<16; j++)    {      mmx_weights[j][0] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][1] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][2] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][3] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][4] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][5] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][6] = 0x00010001 * (weights[4*j + 3] >> 8);      mmx_weights[j][7] = 0x00010001 * (weights[4*j + 3] >> 8);    }  return _pixops_composite_line_22_4a4_mmx (mmx_weights, dest, src[0], src[1], x_step, dest_end, x_init);}#endif /* USE_MMX */static voidcomposite_pixel_color (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha,		       int src_has_alpha, int check_size, guint32 color1, guint32 color2,		       guint r, guint g, guint b, guint a){  int dest_r, dest_g, dest_b;  int check_shift = get_check_shift (check_size);  if ((dest_x >> check_shift) & 1)    {      dest_r = (color2 & 0xff0000) >> 16;      dest_g = (color2 & 0xff00) >> 8;      dest_b = color2 & 0xff;    }  else    {      dest_r = (color1 & 0xff0000) >> 16;      dest_g = (color1 & 0xff00) >> 8;      dest_b = color1 & 0xff;    }  dest[0] = ((0xff0000 - a) * dest_r + r) >> 24;  dest[1] = ((0xff0000 - a) * dest_g + g) >> 24;  dest[2] = ((0xff0000 - a) * dest_b + b) >> 24;  if (dest_has_alpha)    dest[3] = 0xff;  else if (dest_channels == 4)    dest[3] = a >> 16;}static guchar *composite_line_color (int *weights, int n_x, int n_y,		      guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,		      guchar **src, int src_channels, gboolean src_has_alpha,		      int x_init, int x_step, int src_width,		      int check_size, guint32 color1, guint32 color2){  int x = x_init;  int i, j;  int check_shift = get_check_shift (check_size);  int dest_r1, dest_g1, dest_b1;  int dest_r2, dest_g2, dest_b2;  g_return_val_if_fail (check_size != 0, dest);  dest_r1 = (color1 & 0xff0000) >> 16;  dest_g1 = (color1 & 0xff00) >> 8;  dest_b1 = color1 & 0xff;  dest_r2 = (color2 & 0xff0000) >> 16;  dest_g2 = (color2 & 0xff00) >> 8;  dest_b2 = color2 & 0xff;  while (dest < dest_end)    {      int x_scaled = x >> SCALE_SHIFT;      unsigned int r = 0, g = 0, b = 0, a = 0;      int *pixel_weights;            pixel_weights = weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_x * n_y;      for (i=0; i<n_y; i++)	{	  guchar *q = src[i] + x_scaled * src_channels;	  int *line_weights = pixel_weights + n_x * i;	  	  for (j=0; j<n_x; j++)	    {	      unsigned int ta;	      	      if (src_has_alpha)		ta = q[3] * line_weights[j];	      else		ta = 0xff * line_weights[j];		  	      r += ta * q[0];	      g += ta * q[1];	      b += ta * q[2];	      a += ta;	      q += src_channels;	    }	}      if ((dest_x >> check_shift) & 1)	{	  dest[0] = ((0xff0000 - a) * dest_r2 + r) >> 24;	  dest[1] = ((0xff0000 - a) * dest_g2 + g) >> 24;	  dest[2] = ((0xff0000 - a) * dest_b2 + b) >> 24;	}      else	{	  dest[0] = ((0xff0000 - a) * dest_r1 + r) >> 24;	  dest[1] = ((0xff0000 - a) * dest_g1 + g) >> 24;	  dest[2] = ((0xff0000 - a) * dest_b1 + b) >> 24;	}      if (dest_has_alpha)	dest[3] = 0xff;      else if (dest_channels == 4)	dest[3] = a >> 16;	      dest += dest_channels;      x += x_step;      dest_x++;    }  return dest;}#ifdef USE_MMXstatic guchar *composite_line_color_22_4a4_mmx_stub (int *weights, int n_x, int n_y,				      guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,				      guchar **src, int src_channels, gboolean src_has_alpha,				      int x_init, int x_step, int src_width,				      int check_size, guint32 color1, guint32 color2){  guint32 mmx_weights[16][8];  int check_shift = get_check_shift (check_size);  int colors[4];  int j;  for (j=0; j<16; j++)    {      mmx_weights[j][0] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][1] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][2] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][3] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][4] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][5] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][6] = 0x00010001 * (weights[4*j + 3] >> 8);      mmx_weights[j][7] = 0x00010001 * (weights[4*j + 3] >> 8);    }  colors[0] = (color1 & 0xff00) << 8 | (color1 & 0xff);  colors[1] = (color1 & 0xff0000) >> 16;  colors[2] = (color2 & 0xff00) << 8 | (color2 & 0xff);  colors[3] = (color2 & 0xff0000) >> 16;  return _pixops_composite_line_color_22_4a4_mmx (mmx_weights, dest, src[0], src[1], x_step, dest_end, x_init,						  dest_x, check_shift, colors);}#endif /* USE_MMX */static voidscale_pixel (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha,	     int src_has_alpha, int check_size, guint32 color1, guint32 color2,	     guint r, guint g, guint b, guint a){  if (src_has_alpha)    {      if (a)	{	  dest[0] = r / a;	  dest[1] = g / a;	  dest[2] = b / a;	  dest[3] = a >> 16;	}      else	{	  dest[0] = 0;	  dest[1] = 0;	  dest[2] = 0;	  dest[3] = 0;	}    }  else    {      dest[0] = (r + 0xffffff) >> 24;      dest[1] = (g + 0xffffff) >> 24;      dest[2] = (b + 0xffffff) >> 24;            if (dest_has_alpha)	dest[3] = 0xff;    }}static guchar *scale_line (int *weights, int n_x, int n_y,	    guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,	    guchar **src, int src_channels, gboolean src_has_alpha,	    int x_init, int x_step, int src_width,	    int check_size, guint32 color1, guint32 color2){  int x = x_init;  int i, j;  while (dest < dest_end)    {      int x_scaled = x >> SCALE_SHIFT;      int *pixel_weights;      pixel_weights = weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_x * n_y;      if (src_has_alpha)	{	  unsigned int r = 0, g = 0, b = 0, a = 0;	  for (i=0; i<n_y; i++)	    {	      guchar *q = src[i] + x_scaled * src_channels;	      int *line_weights  = pixel_weights + n_x * i;	      	      for (j=0; j<n_x; j++)		{		  unsigned int ta;		  		  ta = q[3] * line_weights[j];		  r += ta * q[0];		  g += ta * q[1];		  b += ta * q[2];		  a += ta;		  		  q += src_channels;		}	    }	  if (a)	    {	      dest[0] = r / a;	      dest[1] = g / a;	      dest[2] = b / a;	      dest[3] = a >> 16;	    }	  else	    {	      dest[0] = 0;	      dest[1] = 0;	      dest[2] = 0;	      dest[3] = 0;	    }	}      else	{	  unsigned int r = 0, g = 0, b = 0;	  for (i=0; i<n_y; i++)	    {	      guchar *q = src[i] + x_scaled * src_channels;	      int *line_weights  = pixel_weights + n_x * i;	      	      for (j=0; j<n_x; j++)		{		  unsigned int ta = line_weights[j];		  		  r += ta * q[0];		  g += ta * q[1];		  b += ta * q[2];		  q += src_channels;		}	    }	  dest[0] = (r + 0xffff) >> 16;	  dest[1] = (g + 0xffff) >> 16;	  dest[2] = (b + 0xffff) >> 16;	  	  if (dest_has_alpha)	    dest[3] = 0xff;	}      dest += dest_channels;            x += x_step;    }  return dest;}#ifdef USE_MMX static guchar *scale_line_22_33_mmx_stub (int *weights, int n_x, int n_y,			   guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,			   guchar **src, int src_channels, gboolean src_has_alpha,			   int x_init, int x_step, int src_width,			   int check_size, guint32 color1, guint32 color2){  guint32 mmx_weights[16][8];  int j;  for (j=0; j<16; j++)    {      mmx_weights[j][0] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][1] = 0x00010001 * (weights[4*j] >> 8);      mmx_weights[j][2] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][3] = 0x00010001 * (weights[4*j + 1] >> 8);      mmx_weights[j][4] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][5] = 0x00010001 * (weights[4*j + 2] >> 8);      mmx_weights[j][6] = 0x00010001 * (weights[4*j + 3] >> 8);      mmx_weights[j][7] = 0x00010001 * (weights[4*j + 3] >> 8);    }  return _pixops_scale_line_22_33_mmx (mmx_weights, dest, src[0], src[1], x_step, dest_end, x_init);}#endif /* USE_MMX */static guchar *scale_line_22_33 (int *weights, int n_x, int n_y,		  guchar *dest, int dest_x, guchar *dest_end, int dest_channels, int dest_has_alpha,		  guchar **src, int src_channels, gboolean src_has_alpha,		  int x_init, int x_step, int src_width,		  int check_size, guint32 color1, guint32 color2){  int x = x_init;  guchar *src0 = src[0];  guchar *src1 = src[1];    while (dest < dest_end)    {      unsigned int r, g, b;      int x_scaled = x >> SCALE_SHIFT;      int *pixel_weights;      guchar *q0, *q1;      int w1, w2, w3, w4;      q0 = src0 + x_scaled * 3;      q1 = src1 + x_scaled * 3;            pixel_weights = weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * 4;      w1 = pixel_weights[0];      w2 = pixel_weights[1];      w3 = pixel_weights[2];      w4 = pixel_weights[3];      r = w1 * q0[0];      g = w1 * q0[1];      b = w1 * q0[2];      r += w2 * q0[3];      g += w2 * q0[4];      b += w2 * q0[5];      r += w3 * q1[0];      g += w3 * q1[1];      b += w3 * q1[2];      r += w4 * q1[3];      g += w4 * q1[4];      b += w4 * q1[5];      dest[0] = (r + 0x8000) >> 16;      dest[1] = (g + 0x8000) >> 16;      dest[2] = (b + 0x8000) >> 16;            dest += 3;      x += x_step;    }    return dest;}static voidprocess_pixel (int *weights, int n_x, int n_y,	       guchar *dest, int dest_x, int dest_channels, int dest_has_alpha,	       guchar **src, int src_channels, gboolean src_has_alpha,	       int x_start, int src_width,	       int check_size, guint32 color1, guint32 color2,	       PixopsPixelFunc pixel_func){  unsigned int r = 0, g = 0, b = 0, a = 0;  int i, j;    for (i=0; i<n_y; i++)    {      int *line_weights  = weights + n_x * i;      for (j=0; j<n_x; j++)	{	  unsigned int ta;	  guchar *q;	  if (x_start + j < 0)	    q = src[i];	  else if (x_start + j < src_width)	    q = src[i] + (x_start + j) * src_channels;	  else	    q = src[i] + (src_width - 1) * src_channels;	  if (src_has_alpha)	    ta = q[3] * line_weights[j];	  else	    ta = 0xff * line_weights[j];	  r += ta * q[0];	  g += ta * q[1];	  b += ta * q[2];	  a += ta;	}    }  (*pixel_func) (dest, dest_x, dest_channels, dest_has_alpha, src_has_alpha, check_size, color1, color2, r, g, b, a);}static void correct_total (int    *weights,                int    n_x,                int    n_y,               int    total,                double overall_alpha){  int correction = (int)(0.5 + 65536 * overall_alpha) - total;  int remaining, c, d, i;    if (correction != 0)    {      remaining = correction;      for (d = 1, c = correction; c != 0 && remaining != 0; d++, c = correction / d) 	for (i = n_x * n_y - 1; i >= 0 && c != 0 && remaining != 0; i--) 	  if (*(weights + i) + c >= 0) 	    {	      *(weights + i) += c;	      remaining -= c;	      if ((0 < remaining && remaining < c) ||		  (0 > remaining && remaining > c))		c = remaining;	    }    }}static int *make_filter_table (PixopsFilter *filter){  int i_offset, j_offset;  int n_x = filter->x.n;  int n_y = filter->y.n;  int *weights = g_new (int, SUBSAMPLE * SUBSAMPLE * n_x * n_y);  for (i_offset=0; i_offset < SUBSAMPLE; i_offset++)    for (j_offset=0; j_offset < SUBSAMPLE; j_offset++)      {        double weight;        int *pixel_weights = weights + ((i_offset*SUBSAMPLE) + j_offset) * n_x * n_y;        int total = 0;        int i, j;        for (i=0; i < n_y; i++)          for (j=0; j < n_x; j++)            {              weight = filter->x.weights[(j_offset * n_x) + j] *                       filter->y.weights[(i_offset * n_y) + i] *                       filter->overall_alpha * 65536 + 0.5;              total += (int)weight;              *(pixel_weights + n_x * i + j) = weight;            }        correct_total (pixel_weights, n_x, n_y, total, filter->overall_alpha);      }  return weights;}static voidpixops_process (guchar         *dest_buf,		int             render_x0,		int             render_y0,		int             render_x1,		int             render_y1,		int             dest_rowstride,		int             dest_channels,		gboolean        dest_has_alpha,		const guchar   *src_buf,		int             src_width,		int             src_height,		int             src_rowstride,		int             src_channels,		gboolean        src_has_alpha,		double          scale_x,		double          scale_y,		int             check_x,		int             check_y,		int             check_size,		guint32         color1,		guint32         color2,		PixopsFilter   *filter,		PixopsLineFunc  line_func,		PixopsPixelFunc pixel_func){  int i, j;  int x, y;			/* X and Y position in source (fixed_point) */    guchar **line_bufs = g_new (guchar *, filter->y.n);  int *filter_weights = make_filter_table (filter);  int x_step = (1 << SCALE_SHIFT) / scale_x; /* X step in source (fixed point) */  int y_step = (1 << SCALE_SHIFT) / scale_y; /* Y step in source (fixed point) */  int check_shift = check_size ? get_check_shift (check_size) : 0;  int scaled_x_offset = floor (filter->x.offset * (1 << SCALE_SHIFT));  /* Compute the index where we run off the end of the source buffer. The furthest   * source pixel we access at index i is:   *   *  ((render_x0 + i) * x_step + scaled_x_offset) >> SCALE_SHIFT + filter->x.n - 1   *   * So, run_end_index is the smallest i for which this pixel is src_width, i.e, for which:   *   *  (i + render_x0) * x_step >= ((src_width - filter->x.n + 1) << SCALE_SHIFT) - scaled_x_offset   *   */#define MYDIV(a,b) ((a) > 0 ? (a) / (b) : ((a) - (b) + 1) / (b))    /* Division so that -1/5 = -1 */    int run_end_x = (((src_width - filter->x.n + 1) << SCALE_SHIFT) - scaled_x_offset);  int run_end_index = MYDIV (run_end_x + x_step - 1, x_step) - render_x0;  run_end_index = MIN (run_end_index, render_x1 - render_x0);  y = render_y0 * y_step + floor (filter->y.offset * (1 << SCALE_SHIFT));  for (i = 0; i < (render_y1 - render_y0); i++)    {      int dest_x;      int y_start = y >> SCALE_SHIFT;      int x_start;      int *run_weights = filter_weights +

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?