⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pixops.c

📁 linux下电话本所依赖的一些图形库
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <config.h>#include <math.h>#include <glib.h>#include "pixops.h"#include "pixops-internal.h"#define SUBSAMPLE_BITS 4#define SUBSAMPLE (1 << SUBSAMPLE_BITS)#define SUBSAMPLE_MASK ((1 << SUBSAMPLE_BITS)-1)#define SCALE_SHIFT 16typedef struct _PixopsFilter PixopsFilter;typedef struct _PixopsFilterDimension PixopsFilterDimension;struct _PixopsFilterDimension{  int n;  double offset;  double *weights;};struct _PixopsFilter{  PixopsFilterDimension x;  PixopsFilterDimension y;  double overall_alpha;}; typedef guchar *(*PixopsLineFunc) (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);typedef void (*PixopsPixelFunc) (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);static intget_check_shift (int check_size){  int check_shift = 0;  g_return_val_if_fail (check_size >= 0, 4);  while (!(check_size & 1))    {      check_shift++;      check_size >>= 1;    }  return check_shift;}static voidpixops_scale_nearest (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 i;  int x;  int x_step = (1 << SCALE_SHIFT) / scale_x;  int y_step = (1 << SCALE_SHIFT) / scale_y;  int xmax, xstart, xstop, x_pos, y_pos;  const guchar *p;#define INNER_LOOP(SRC_CHANNELS,DEST_CHANNELS,ASSIGN_PIXEL)     \      xmax = x + (render_x1 - render_x0) * x_step;              \      xstart = MIN (0, xmax);                                   \      xstop = MIN (src_width << SCALE_SHIFT, xmax);             \      p = src + (CLAMP (x, xstart, xstop) >> SCALE_SHIFT) * SRC_CHANNELS; \      while (x < xstart)                                        \        {                                                       \          ASSIGN_PIXEL;                                         \          dest += DEST_CHANNELS;                                \          x += x_step;                                          \        }                                                       \      while (x < xstop)                                         \        {                                                       \          p = src + (x >> SCALE_SHIFT) * SRC_CHANNELS;          \          ASSIGN_PIXEL;                                         \          dest += DEST_CHANNELS;                                \          x += x_step;                                          \        }                                                       \      x_pos = x >> SCALE_SHIFT;                                 \      p = src + CLAMP (x_pos, 0, src_width - 1) * SRC_CHANNELS; \      while (x < xmax)                                          \        {                                                       \          ASSIGN_PIXEL;                                         \          dest += DEST_CHANNELS;                                \          x += x_step;                                          \        }  for (i = 0; i < (render_y1 - render_y0); i++)    {      const guchar *src;      guchar       *dest;      y_pos = ((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT;      y_pos = CLAMP (y_pos, 0, src_height - 1);      src  = src_buf + y_pos * src_rowstride;      dest = dest_buf + i * dest_rowstride;      x = render_x0 * x_step + x_step / 2;      if (src_channels == 3)	{	  if (dest_channels == 3)	    {	      INNER_LOOP (3, 3, dest[0]=p[0];dest[1]=p[1];dest[2]=p[2]);	    }	  else	    {	      INNER_LOOP (3, 4, dest[0]=p[0];dest[1]=p[1];dest[2]=p[2];dest[3]=0xff);	    }	}      else if (src_channels == 4)	{	  if (dest_channels == 3)	    {	      INNER_LOOP (4, 3, dest[0]=p[0];dest[1]=p[1];dest[2]=p[2]);	    }	  else	    {	      guint32 *p32;	      INNER_LOOP(4, 4, p32=(guint32*)dest;*p32=*((guint32*)p));	    }	}    }}static voidpixops_composite_nearest (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            overall_alpha){  int i;  int x;  int x_step = (1 << SCALE_SHIFT) / scale_x;  int y_step = (1 << SCALE_SHIFT) / scale_y;  int xmax, xstart, xstop, x_pos, y_pos;  const guchar *p;  unsigned int  a0;  for (i = 0; i < (render_y1 - render_y0); i++)    {      const guchar *src;      guchar       *dest;      y_pos = ((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT;      y_pos = CLAMP (y_pos, 0, src_height - 1);      src  = src_buf + y_pos * src_rowstride;      dest = dest_buf + i * dest_rowstride;      x = render_x0 * x_step + x_step / 2;            INNER_LOOP(src_channels, dest_channels,	  if (src_has_alpha)	    a0 = (p[3] * overall_alpha) / 0xff;	  else	    a0 = overall_alpha;          switch (a0)            {            case 0:              break;            case 255:              dest[0] = p[0];              dest[1] = p[1];              dest[2] = p[2];              if (dest_has_alpha)                dest[3] = 0xff;              break;            default:              if (dest_has_alpha)                {                  unsigned int w0 = 0xff * a0;                  unsigned int w1 = (0xff - a0) * dest[3];                  unsigned int w = w0 + w1;		  dest[0] = (w0 * p[0] + w1 * dest[0]) / w;		  dest[1] = (w0 * p[1] + w1 * dest[1]) / w;		  dest[2] = (w0 * p[2] + w1 * dest[2]) / w;		  dest[3] = w / 0xff;                }              else                {                  unsigned int a1 = 0xff - a0;		  unsigned int tmp;		  tmp = a0 * p[0] + a1 * dest[0] + 0x80;                  dest[0] = (tmp + (tmp >> 8)) >> 8;		  tmp = a0 * p[1] + a1 * dest[1] + 0x80;                  dest[1] = (tmp + (tmp >> 8)) >> 8;		  tmp = a0 * p[2] + a1 * dest[2] + 0x80;                  dest[2] = (tmp + (tmp >> 8)) >> 8;                }              break;            }	);	          }}static voidpixops_composite_color_nearest (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            overall_alpha,				int            check_x,				int            check_y,				int            check_size,				guint32        color1,				guint32        color2){  int i, j;  int x;  int x_step = (1 << SCALE_SHIFT) / scale_x;  int y_step = (1 << SCALE_SHIFT) / scale_y;  int r1, g1, b1, r2, g2, b2;  int check_shift = get_check_shift (check_size);  int xmax, xstart, xstop, x_pos, y_pos;  const guchar *p;  unsigned int  a0;  for (i = 0; i < (render_y1 - render_y0); i++)    {      const guchar *src;      guchar       *dest;      y_pos = ((i + render_y0) * y_step + y_step / 2) >> SCALE_SHIFT;      y_pos = CLAMP (y_pos, 0, src_height - 1);      src  = src_buf + y_pos * src_rowstride;      dest = dest_buf + i * dest_rowstride;      x = render_x0 * x_step + x_step / 2;                  if (((i + check_y) >> check_shift) & 1)	{	  r1 = (color2 & 0xff0000) >> 16;	  g1 = (color2 & 0xff00) >> 8;	  b1 = color2 & 0xff;	  r2 = (color1 & 0xff0000) >> 16;	  g2 = (color1 & 0xff00) >> 8;	  b2 = color1 & 0xff;	}      else	{	  r1 = (color1 & 0xff0000) >> 16;	  g1 = (color1 & 0xff00) >> 8;	  b1 = color1 & 0xff;	  r2 = (color2 & 0xff0000) >> 16;	  g2 = (color2 & 0xff00) >> 8;	  b2 = color2 & 0xff;	}      j = 0;      INNER_LOOP(src_channels, dest_channels,	  if (src_has_alpha)	    a0 = (p[3] * overall_alpha + 0xff) >> 8;	  else	    a0 = overall_alpha;          switch (a0)            {            case 0:              if (((j + check_x) >> check_shift) & 1)                {                  dest[0] = r2;                   dest[1] = g2;                   dest[2] = b2;                }              else                {                  dest[0] = r1;                   dest[1] = g1;                   dest[2] = b1;                }            break;            case 255:	      dest[0] = p[0];	      dest[1] = p[1];	      dest[2] = p[2];              break;            default:		     {		       unsigned int tmp;              if (((j + check_x) >> check_shift) & 1)                {                  tmp = ((int) p[0] - r2) * a0;                  dest[0] = r2 + ((tmp + (tmp >> 8) + 0x80) >> 8);                  tmp = ((int) p[1] - g2) * a0;                  dest[1] = g2 + ((tmp + (tmp >> 8) + 0x80) >> 8);                  tmp = ((int) p[2] - b2) * a0;                  dest[2] = b2 + ((tmp + (tmp >> 8) + 0x80) >> 8);                }              else                {                  tmp = ((int) p[0] - r1) * a0;                  dest[0] = r1 + ((tmp + (tmp >> 8) + 0x80) >> 8);                  tmp = ((int) p[1] - g1) * a0;                  dest[1] = g1 + ((tmp + (tmp >> 8) + 0x80) >> 8);                  tmp = ((int) p[2] - b1) * a0;                  dest[2] = b1 + ((tmp + (tmp >> 8) + 0x80) >> 8);                }		     }              break;            }	  	  if (dest_channels == 4)	    dest[3] = 0xff;		 j++;	);    }}#undef INNER_LOOPstatic voidcomposite_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 (dest_has_alpha)    {      unsigned int w0 = a - (a >> 8);      unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];      unsigned int w = w0 + w1;            if (w != 0)	{	  dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;	  dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;	  dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;	  dest[3] = w / 0xff00;	}      else	{	  dest[0] = 0;	  dest[1] = 0;	  dest[2] = 0;	  dest[3] = 0;	}    }  else    {      dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;      dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;      dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;    }}static guchar *composite_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;      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_has_alpha)	{	  unsigned int w0 = a - (a >> 8);	  unsigned int w1 = ((0xff0000 - a) >> 8) * dest[3];	  unsigned int w = w0 + w1;	  if (w != 0)	    {	      dest[0] = (r - (r >> 8) + w1 * dest[0]) / w;	      dest[1] = (g - (g >> 8) + w1 * dest[1]) / w;	      dest[2] = (b - (b >> 8) + w1 * dest[2]) / w;	      dest[3] = w / 0xff00;	    }	  else	    {	      dest[0] = 0;	      dest[1] = 0;	      dest[2] = 0;	      dest[3] = 0;	    }	}      else	{	  dest[0] = (r + (0xff0000 - a) * dest[0]) / 0xff0000;	  dest[1] = (g + (0xff0000 - a) * dest[1]) / 0xff0000;	  dest[2] = (b + (0xff0000 - a) * dest[2]) / 0xff0000;	}            dest += dest_channels;      x += x_step;    }  return dest;}static guchar *composite_line_22_4a4 (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];  g_return_val_if_fail (src_channels != 3, dest);  g_return_val_if_fail (src_has_alpha, dest);    while (dest < dest_end)    {      int x_scaled = x >> SCALE_SHIFT;      unsigned int r, g, b, a, ta;      int *pixel_weights;      guchar *q0, *q1;      int w1, w2, w3, w4;            q0 = src0 + x_scaled * 4;      q1 = src1 + x_scaled * 4;            pixel_weights = (int *)((char *)weights + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS - 4)) & (SUBSAMPLE_MASK << 4)));            w1 = pixel_weights[0];      w2 = pixel_weights[1];      w3 = pixel_weights[2];      w4 = pixel_weights[3];      a = w1 * q0[3];      r = a * q0[0];      g = a * q0[1];      b = a * q0[2];      ta = w2 * q0[7];      r += ta * q0[4];      g += ta * q0[5];      b += ta * q0[6];      a += ta;      ta = w3 * q1[3];      r += ta * q1[0];      g += ta * q1[1];      b += ta * q1[2];      a += ta;      ta = w4 * q1[7];      r += ta * q1[4];      g += ta * q1[5];      b += ta * q1[6];      a += ta;      dest[0] = ((0xff0000 - a) * dest[0] + r) >> 24;      dest[1] = ((0xff0000 - a) * dest[1] + g) >> 24;      dest[2] = ((0xff0000 - a) * dest[2] + b) >> 24;      dest[3] = a >> 16;            dest += 4;      x += x_step;    }  return dest;}#ifdef USE_MMXstatic guchar *composite_line_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,

⌨️ 快捷键说明

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