图片任意角度旋转 梯形变换 任意四边形变换

#include <opencv.hpp>
using namespace cv;
typedef int s32;
typedef long long s64;
typedef s32 cfixed;
typedef  unsigned char u8;

#define cfixed_from_int(i)		(((cfixed)(i)) << 16)
#define cfixed_from_float(x)	((cfixed)((x) * 65536.0f))
#define cfixed_from_double(d)	((cfixed)((d) * 65536.0))
#define cfixed_to_int(f)		((f) >> 16)
#define cfixed_to_float(x)		((float)((x) / 65536.0f))
#define cfixed_const_1			(cfixed_from_int(1))
#define cfixed_const_e			((cfixed)(1))
#define cfixed_const_1_m_e		(cfixed_const_1 - cfixed_const_e)
#define cfixed_const_half		(cfixed_const_1 >> 1)
#define cfixed_frac(f)			((f) & cfixed_const_1_m_e)
#define cfixed_floor(f)			((f) & (~cfixed_const_1_m_e))
#define cfixed_ceil(f)			(cfixed_floor((f) + 0xffff))
#define cfixed_mul(x, y)		((cfixed)((((s64)(x)) * (y)) >> 16))
#define cfixed_div(x, y)		((cfixed)((((s64)(x)) << 16) / (y)))
#define cfixed_const_max		((s64)0x7fffffff)
#define cfixed_const_min		(-((((s64)1) << 31)))

//定点数辅助
#define IPIXEL_EPSILON			((cfixed)(2))
#define IPIXEL_IS_SAME(a, b)	(ipixel_within_epsilon(a, b, IPIXEL_EPSILON))
#define IPIXEL_IS_ZERO(a)		(ipixel_within_epsilon(a, 0, IPIXEL_EPSILON))
#define IPIXEL_IS_ONE(a)		(IPIXEL_IS_SAME(a, cfixed_const_1))
#define IPIXEL_IS_INT(a)		(IPIXEL_IS_ZERO(cfixed_frac(a)))
#define IPIXEL_IS_UNIT(a)		(IPIXEL_IS_SAME(a, cfixed_const_1) || \
								 IPIXEL_IS_SAME(a, -cfixed_const_1) || \
								 IPIXEL_IS_ZERO(a))

enum 
{
	IPIXEL_FILTER_BILINEAR	= 0,	// 滤波模式:双线性过滤采样
	IPIXEL_FILTER_NEAREST	= 1,	// 滤波模式:最近采样
};


// 点的定义
typedef struct 
{
	cfixed x;
	cfixed y;
}ipixel_point_fixed_t;

// 矢量定义
typedef struct 
{
	cfixed vector[3];
}ipixel_vector_t;

// 矩阵定义
typedef struct 
{
	cfixed matrix[3][3];
}ipixel_transform_t;

// 直线定义
typedef struct 
{
	ipixel_point_fixed_t p1;
	ipixel_point_fixed_t p2;
}ipixel_line_fixed_t;


// 像素点定义
typedef struct 
{
	u8 rgb[3];
}ipixel_pixel_t;


static inline s32 ipixel_within_epsilon(cfixed a, cfixed b, cfixed epsilon)
{
	cfixed c = a - b;
	if (c < 0) c = -c;
	return c <= epsilon;
}


// 线段与y轴相交的x坐标,ceil为是否向上去整
static inline cfixed ipixel_line_fixed_x(const ipixel_line_fixed_t *l,
										 cfixed y, s32 ceil)
{
	cfixed dx = l->p2.x - l->p1.x;
	s64 ex = ((s64)(y - l->p1.y)) * dx;
	cfixed dy = l->p2.y - l->p1.y;
	if (ceil) ex += (dy - 1);
	return l->p1.x + (cfixed)(ex / dy);
}


static inline s32 ipixel_line_span_bound(const ipixel_line_fixed_t *t, s32 y, s32 *x)
{
	cfixed x1, x2, y1, y2;
	s32 yt, yb;
	yt = cfixed_to_int(min(t->p1.y , t->p2.y));
	yb = cfixed_to_int(max(t->p1.y , t->p2.y));
	if (y < yt || y >= yb) return -2;
	
	y1 = cfixed_from_int(y);
	y2 = cfixed_from_int(y) + cfixed_const_1_m_e;
	x1 = cfixed_ceil(ipixel_line_fixed_x(t, y1, 0));
	x2 = cfixed_ceil(ipixel_line_fixed_x(t, y2, 0));
	*x = cfixed_to_int((x1 > x2)? x1 : x2);
	
	return 0;
}


static inline s32 ipixel_lines_bound(ipixel_line_fixed_t *t, int n ,s32 y, s32 *lx, s32 *rx)
{
	s32 xmin = 0x7fff, xmax = -0x7fff;
	s32 x[2];
	
	for (s32 i = 0 , j = 0; i < n;  i++) 
	{
		if (ipixel_line_span_bound(&t[i], y, &x[j]) == 0) 
		{
			j++;
		}
	}

	if (j == 2) 
	{
		*lx = min(x[0],x[1]);
		*rx = max(x[0],x[1]);
		return 0;
	}

	return -1;
}



s32 ipixel_span_fetch(const Mat *img, s32 offset, s32 line, s32 width, u8 *card, const ipixel_transform_t *t);


/* 绕任一点的旋转 变换矩阵(顺时针)
 *
 * 用下面的线性方程组来表示关系,求解方程组可以得到矩阵:
 * |Xdst|    |  cos  sin   (1-cos)*center.x - sin*center.y| |Xsrc|
 * |Ydst|    | -sin  cos   sin*center.x + (1-cos)*center.y| |Ysrc|
 * |  1 |    |   0    0                 1                 | |  1 |
 */

s32 ibitmap_rotate2D(Mat *dst,Mat *src,float angle)
{
	angle *= 3.1415926f/180;
    cfixed  alpha = cfixed_from_float(cos(angle));  
    cfixed  beta  = cfixed_from_float(sin(angle));
	
	ipixel_point_fixed_t center = {0};	
	center.x = cfixed_from_float(src->cols/2.0);
	center.y = cfixed_from_float(src->rows/2.0);

	cfixed one_sub_alpha = cfixed_const_1 - alpha;
	s64 onesubalpha_mul_centerx = (s64)one_sub_alpha * center.x;
	s64 onesubalpha_mul_centery = (s64)one_sub_alpha * center.y;
	s64 beta_mul_centerx = (s64)beta * center.x;
	s64 beta_mul_centery = (s64)beta * center.y; 
	
	ipixel_transform_t matrix = {0};
	matrix.matrix[0][0] =  alpha;
	matrix.matrix[0][1] =  beta;
	matrix.matrix[0][2] = (onesubalpha_mul_centerx - beta_mul_centery)>>16;
	matrix.matrix[1][0] =  -beta;
	matrix.matrix[1][1] =  alpha;
	matrix.matrix[1][2] = (onesubalpha_mul_centery + beta_mul_centerx)>>16;
	matrix.matrix[2][0] =  0;
	matrix.matrix[2][1] =  0;	
	matrix.matrix[2][2] =  cfixed_const_1;

	ipixel_point_fixed_t srcQuad[4] = {0};
	ipixel_point_fixed_t dstQuad[4] = {0};

	srcQuad[0].x = 0;
	srcQuad[0].y = 0;
 	srcQuad[1].x = 0;
	srcQuad[1].y = cfixed_from_int(src->rows);
	srcQuad[2].x = cfixed_from_int(src->cols);
	srcQuad[2].y = cfixed_from_int(src->rows);
	srcQuad[3].x = cfixed_from_int(src->cols);
	srcQuad[3].y = 0;
	
	cfixed minX = 0x7fffffff;
	cfixed maxX = 0x80000000;
	cfixed minY = 0x7fffffff;
	cfixed maxY = 0x80000000;
	
	cfixed offsetx = cfixed_from_float((dst->cols - src->cols)/2.0);
	cfixed offsety = cfixed_from_float((dst->rows - src->rows)/2.0);
	
	for (s32 i = 0; i < 4; i++) 
	{
		dstQuad[i].x = (cfixed)(((s64)srcQuad[i].x * (s64)matrix.matrix[0][0] + (s64)srcQuad[i].y * (s64)matrix.matrix[0][1])>>16) + matrix.matrix[0][2] + offsetx;
		dstQuad[i].y = (cfixed)(((s64)srcQuad[i].x * (s64)matrix.matrix[1][0] + (s64)srcQuad[i].y * (s64)matrix.matrix[1][1])>>16) + matrix.matrix[1][2] + offsety;
		if(dstQuad[i].x < minX) minX = dstQuad[i].x;
		if(dstQuad[i].x > maxX) maxX = dstQuad[i].x;
		if(dstQuad[i].y < minY) minY = dstQuad[i].y;
		if(dstQuad[i].y > maxY) maxY = dstQuad[i].y;
	}

	matrix.matrix[0][0] =  alpha;
	matrix.matrix[0][1] =  - beta;
	matrix.matrix[0][2] =  (onesubalpha_mul_centerx + beta_mul_centery - (s64)alpha*offsetx + (s64)beta*offsety)>>16;
	matrix.matrix[1][0] =  beta;
	matrix.matrix[1][1] =  alpha;
	matrix.matrix[1][2] =  (onesubalpha_mul_centery - beta_mul_centerx - (s64)alpha*offsety - (s64)beta*offsetx)>>16;
	matrix.matrix[2][0] =  0;
	matrix.matrix[2][1] =  0;	
	matrix.matrix[2][2] =  cfixed_const_1;	


	
	//四根直线
	ipixel_line_fixed_t lines[4] = {0};
	for (s32 i = 0 ; i < 4 ;i++)
	{
		lines[i].p1 = dstQuad[i];
		lines[i].p2 = dstQuad[(i+1)%4];
	}

	//生成扫描区域
	s32 width  = cfixed_to_int(maxX - minX);
	s32 height = cfixed_to_int(maxY - minY);
	s32 starty = cfixed_to_int(minY);
	s32 endx   = cfixed_to_int(maxX); 

	size_t BuffSize = dst->step;
	u8 *card = (u8*)malloc(BuffSize);  //工作空间申请
	
	// 主要绘制循环
	for (s32 j = 0; j < height; j++) 
	{
		s32 xl, xr, xw;
		s32 line = j + starty;
		
		// 取得该扫描的X轴左右对应坐标
		if (ipixel_lines_bound(&lines[0],4,line, &xl, &xr) != 0) 
			continue;

		if (xl < 0) xl = 0; 
		if (xr >= endx) xr = endx - 1;

		xw = xr - xl;

		memset(card,0,BuffSize);
		ipixel_span_fetch(src, xl, line, xw, card, &matrix);
		memcpy(dst->data + dst->step*line  + xl*dst->elemSize(), card, xw*dst->elemSize());
	}
	
	free(card);
	return 0;
}

#define IMATRIX_SOLVE_WORKMEM(n, m) ((sizeof(s32) * n + sizeof(float) * (m * n + n * n)))

// solve X from AX=B, result is saved to X
// A(0-(n-1), 0-(n-1)), X(0-(n-1), 0-(m-1)), B(0-(n-1), 0-(m-1))
// A(i, j) = A[i * n + j], B(i, j) = B[i * m + j]
// returns zero for success, others for error.
s32 imatrix_solve_n_m(const float A[], const float B[], float X[], s32 n, s32 m)
{
	// 求解矩阵所需要的临时内存大小


	u8 *workmem = (u8*)malloc(IMATRIX_SOLVE_WORKMEM(n, m));
	s32 *js, l, k, i, j, is, p, q;
	float *a, *b, d, t;

	// initialize 
	a = (float*)(workmem + sizeof(s32) * n);
	b = (float*)(workmem + sizeof(s32) * n + sizeof(float) * n * n);

	for (i = n * n - 1; i >= 0; i--) 
		a[i] = A[i];
	for (i = m * n - 1; i >= 0; i--) 
		b[i] = B[i];

	js = (s32*)workmem;
	is = 0;
	l = 1;

	// solve main loop
	for (k = 0; k <= n - 1; k++) 
	{ 
		d = 0.0;
		for (i = k; i <= n - 1; i++) 
		{
			for (j = k; j <= n - 1; j++)
			{ 
				t = a[i * n + j];

				if (t < 0) 
					t = -t;

				if (t > d) 
				{ 
					d = t; 
					js[k] = j; 
					is = i; 
				}
			}
		}

		if (d + 1.0 == 1.0) 
			l = 0;
		else
		{ 
			if (js[k] != k) 
			{
				for (i = 0; i <= n - 1; i++) 
				{ 
					p = i * n + k; q = i * n + js[k];
					t = a[p]; a[p] = a[q]; a[q] = t;
				}
			}
			if (is != k) 
			{ 
				for (j = k; j <= n - 1; j++) 
				{ 
					p = k * n + j; 
					q = is * n + j;
					t = a[p]; 
					a[p] = a[q]; 
					a[q] = t;
				}
				for (j = 0; j <= m - 1; j++) 
				{ 
					p = k * m + j; 
					q = is * m + j;
					t = b[p]; 
					b[p] = b[q]; 
					b[q] = t;
				}
			}
		}

		// check if no result
		if (l == 0)
		{
			return -1;
		}

		d = a[k * n + k];

		for (j = k + 1; j <= n - 1; j++) 
		{ 
			p = k * n + j; 
			a[p] = a[p] / d;
		}

		for (j = 0; j <= m - 1; j++) 
		{
			p = k * m + j; 
			b[p] = b[p] / d;
		}

		for (j = k + 1; j <= n - 1; j++) 
		{
			for (i = 0; i <= n - 1; i++) 
			{ 
				p = i * n + j;
				if (i != k) 
				{
					a[p] = a[p] - a[i * n + k] * a[k * n + j];
				}
			}
		}

		for (j = 0; j <= m-1; j++) 
		{
			for (i = 0; i <= n - 1; i++) 
			{ 
				p = i * m + j;
				if (i != k) 
				{
					b[p] = b[p] - a[i * n + k] * b[k * m + j];
				}
			}
		}
	}



	for (k = n - 1; k >= 0; k--)
	{
		if (js[k] != k) 
		{
			for (j = 0; j <= m - 1; j++) 
			{ 
				p = k * m + j; q = js[k] * m + j;
				t = b[p]; b[p] = b[q]; b[q] = t;
			}
		}
	}

	for (i = m * n - 1; i >= 0; i--) 
		X[i] = b[i];

	free(workmem);
	return 0;
}


/* 计算透视投影的变换矩阵
 *      c00*xi + c01*yi + c02
 * ui = ---------------------
 *      c20*xi + c21*yi + c22
 *
 *      c10*xi + c11*yi + c12
 * vi = ---------------------
 *      c20*xi + c21*yi + c22
 *
 * 用下面的线性方程组来表示关系,求解方程组可以得到矩阵:
 * / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0\
 * | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
 * | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
 * | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|,
 * |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
 * |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
 * |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
 * \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
 *
 * 其中:
 *   cij - 变换剧照的元素, c22 = 1
 */
s32 itransform_perspective(float m[], const float src[], const float dst[])
{
	float a[8][8], b[8], x[8];
	s32 i;

    for (i = 0; i < 4; i++)
	{
        a[i][0] = a[i + 4][3] = src[i * 2 + 0];
        a[i][1] = a[i + 4][4] = src[i * 2 + 1];
        a[i][2] = a[i + 4][5] = 1;
        a[i][3] = a[i][4] = a[i][5] = 0;
        a[i + 4][0] = a[i + 4][1] = a[i + 4][2] = 0;
        a[i][6] = -src[i * 2 + 0] * dst[i * 2 + 0];
        a[i][7] = -src[i * 2 + 1] * dst[i * 2 + 0];
        a[i + 4][6] = -src[i * 2 + 0] * dst[i * 2 + 1];
        a[i + 4][7] = -src[i * 2 + 1] * dst[i * 2 + 1];
        b[i] = dst[i * 2 + 0];
        b[i + 4] = dst[i * 2 + 1];
    }

	if (imatrix_solve_n_m(&a[0][0], b, x, 8, 1) != 0)
		return -1;

	for (i = 0; i < 8; i++) m[i] = x[i];
	m[8] = 1.0;
	
	return 0;
}



// 初始化透视矩阵
s32 ipixel_transform_init_perspective(ipixel_transform_t *matrix,
									  const  ipixel_point_fixed_t *src,
									  const  ipixel_point_fixed_t *dst)
{
	float fsrc[8];
	float fdst[8];
	float fmat[9];
	s32 i, j;
	s64 n;

	for (i = 0; i < 4; i++)
	{
		fsrc[i * 2 + 0] = cfixed_to_float(src[i].x);
		fsrc[i * 2 + 1] = cfixed_to_float(src[i].y);
		fdst[i * 2 + 0] = cfixed_to_float(dst[i].x);
		fdst[i * 2 + 1] = cfixed_to_float(dst[i].y);
	}

	if (itransform_perspective(fmat, fsrc, fdst) != 0)
		return -1;

	for (i = 0; i < 3; i++) 
	{
		for (j = 0; j < 3; j++) 
		{
			n = ((s64)( fmat[i * 3 + j] * 65536.0));  //注意
			if (n < cfixed_const_min || n > cfixed_const_max)
			{
				return -2;
			}
			matrix->matrix[i][j] = (cfixed)n;
		}
	}
	return 0;
}



s32 ibitmap_quadtransform(Mat *dst,Mat *src,ipixel_point_fixed_t* p )
{
	//四根直线
	ipixel_line_fixed_t lines[4] = {0};
	for (s32 i = 0 ; i < 4 ;i++)
	{
		lines[i].p1 = p[i];
		lines[i].p2 = p[(i+1)%4];
	}

	cfixed minX = 0x7fffffff;
	cfixed maxX = 0x80000000;
	cfixed minY = 0x7fffffff;
	cfixed maxY = 0x80000000;
	for (s32 i = 0; i < 4; i++) 
	{
		if(p[i].x < minX) minX = p[i].x;
		if(p[i].x > maxX) maxX = p[i].x;
		if(p[i].y < minY) minY = p[i].y;
		if(p[i].y > maxY) maxY = p[i].y;
	}
	//生成扫描区域
	s32 width  = cfixed_to_int(maxX - minX);
	s32 height = cfixed_to_int(maxY - minY);
	s32 starty = cfixed_to_int(minY);
	s32 endx   = cfixed_to_int(maxX); 

	size_t BuffSize = dst->step;
	u8 *card = (u8*)malloc(BuffSize);  //工作空间申请

	ipixel_point_fixed_t srcQuad[4];
	srcQuad[0].x = 0;
	srcQuad[0].y = 0;
	srcQuad[1].x = 0;
	srcQuad[1].y = cfixed_from_int(src->rows);
	srcQuad[2].x = cfixed_from_int(src->cols);
	srcQuad[2].y = cfixed_from_int(src->rows);
	srcQuad[3].x = cfixed_from_int(src->cols);
	srcQuad[3].y = 0;

	//计算变换矩阵
	ipixel_transform_t matrix = {0};

	if (ipixel_transform_init_perspective(&matrix, p,&srcQuad[0]) != 0) 
				return -8;

		
	// 主要绘制循环
	for (s32 j = 0; j < height; j++) 
	{
		s32 xl, xr, xw;
		s32 line = j + starty;
		
		// 取得该扫描的X轴左右对应坐标
		if (ipixel_lines_bound(&lines[0],4,line, &xl, &xr) != 0) 
			continue;

		if (xl < 0) xl = 0; 
		if (xr >= endx) xr = endx - 1;

		xw = xr - xl;

		memset(card,0,BuffSize);
		ipixel_span_fetch(src, xl, line, xw, card, &matrix);
		memcpy(dst->data + dst->step*line  + xl*dst->elemSize(), card, xw*dst->elemSize());
	}
	
	free(card);
	return 0;
}

// 矩阵同点相乘: matrix * vector
s32 ipixel_transform_point(const ipixel_transform_t *t,ipixel_vector_t *vector)
{
	ipixel_vector_t result = {0};
	s64 partial;
	s64 v;
	s32 i, j;

	for (j = 0; j < 3; j++) 
	{
		v = 0;
		for (i = 0; i < 3; i++) 
		{
			partial = ((s64)t->matrix[j][i])*((s64)vector->vector[i]);
			v += partial >> 16 ;
		}
		if (v > cfixed_const_max || v < cfixed_const_min)
			return -1;
		result.vector[j] = (cfixed)v;
	}

	*vector = result;

	if (vector->vector[2] == 0) 
		return -2;

	return 0;
}

void ibitmap_fetch_pixel(const Mat* img , ipixel_pixel_t* pr ,cfixed x, cfixed y)
{
	s32 x0 = (x < 0)? 0 : (x >= img->cols)? (img->cols - 1) : x;
	s32 y0 = (y < 0)? 0 : (y >= img->rows)? (img->rows - 1) : y;

	u8* pdata = img->data + y0*img->step + x0 * img->elemSize();
	
	pr->rgb[0] = pdata[0];
	pr->rgb[1] = pdata[1];
	pr->rgb[2] = pdata[2];
}

void ibitmap_fetch_pixel_bilinear(const Mat* img , ipixel_pixel_t* pr ,cfixed x, cfixed y)
{
	cfixed x1 = x - cfixed_const_1 / 2; 
	cfixed y1 = y - cfixed_const_1 / 2; 
	cfixed distx = (x1 >> 8) & 0xff;
	cfixed disty = (y1 >> 8) & 0xff;
	x1 = cfixed_to_int(x1); 
	y1 = cfixed_to_int(y1); 
	s32 x2 = x1 + 1; 
	s32 y2 = y1 + 1; 

	ipixel_pixel_t c[2][2] = {0};
	ibitmap_fetch_pixel(img ,&c[0][0],x1 ,y1 );
	ibitmap_fetch_pixel(img ,&c[0][1],x2 ,y1 );
	ibitmap_fetch_pixel(img ,&c[1][0],x1 ,y2 );
	ibitmap_fetch_pixel(img ,&c[1][1],x2 ,y2 );

	s32 distxy = distx * disty;
	s32 distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
	s32 distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
	s32 distixiy = 256 * 256 - (disty << 8) - (distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */
	
	for(s32 i = 0 ; i < 3 ; i++)
	{
		pr->rgb[i] = cfixed_to_int(c[0][0].rgb[i] * distixiy + c[0][1].rgb[i] * distxiy +c[1][0].rgb[i] * distixy + c[1][1].rgb[i] * distxy);
	}
}

s32 ipixel_span_fetch(const Mat *img, s32 offset, s32 line, s32 width, u8 *card, const ipixel_transform_t *t )
{
	ipixel_vector_t vec, step;
	vec.vector[0] = cfixed_from_int(offset) + cfixed_const_half;
	vec.vector[1] = cfixed_from_int(line) + cfixed_const_half;
	vec.vector[2] = cfixed_const_1;

	if (t != NULL)
	{
		if (ipixel_transform_point(t, &vec) != 0) 
			return -12;
		
		step.vector[0] = t->matrix[0][0];
		step.vector[1] = t->matrix[1][0];
		step.vector[2] = t->matrix[2][0];
	}	
	else 
	{
		step.vector[0] = cfixed_const_1;
		step.vector[1] = 0;
		step.vector[2] = 0;
	}

	if (IPIXEL_IS_ZERO(step.vector[2])) 
	{
		step.vector[2] = 0;

		if (IPIXEL_IS_ONE(vec.vector[2])) 
			vec.vector[2] = cfixed_const_1;

		if (vec.vector[2] != cfixed_const_1) 
		{
			cfixed w = vec.vector[2];
			vec.vector[0] = cfixed_div(vec.vector[0], w);
			vec.vector[1] = cfixed_div(vec.vector[1], w);
			vec.vector[2] = cfixed_const_1;
			step.vector[0] = cfixed_div(step.vector[0], w);
			step.vector[1] = cfixed_div(step.vector[1], w);
			step.vector[2] = cfixed_div(step.vector[2], w);
		}
	}

	cfixed u, v, w, du, dv, dw, x, y; 
	u = vec.vector[0]; 
	v = vec.vector[1]; 
	w = vec.vector[2]; 
	du = step.vector[0]; 
	dv = step.vector[1]; 
	dw = step.vector[2]; 

	u8* pdata = NULL;
	ipixel_pixel_t pixel = {0};
	s32 filter = IPIXEL_FILTER_BILINEAR;  //IPIXEL_FILTER_NEAREST
	if (filter == IPIXEL_FILTER_BILINEAR)
	{ 
		if (w == cfixed_const_1 && dw == 0) 
		{ 
			for (; width > 0; width--) 
			{ 
				ibitmap_fetch_pixel_bilinear(img , &pixel ,u, v);
				memcpy(card , &pixel , img->elemSize());
				card += img->elemSize(); 
				u += du;
				v += dv;  
				w += dw;
			} 
		}	
		else 
		{ 
			for (; width > 0;  width--)
			{ 
				if (w != 0) 
				{ 
					x = cfixed_div(u, w); 
					y = cfixed_div(v, w); 
				}	
				else 
				{  
					x = 0, y = 0; 
				} 
				ibitmap_fetch_pixel_bilinear(img , &pixel ,x, y );
				memcpy(card , &pixel , img->elemSize());
				card += img->elemSize(); 
				u += du;
				v += dv; 
				w += dw;
			} 
		} 
	}
	else//IPIXEL_FILTER_NEAREST
	{
		if (w == cfixed_const_1 && dw == 0) 
		{ 
			for (; width > 0; width--) 
			{ 
				ibitmap_fetch_pixel(img , &pixel ,u, v );
				memcpy(card , &pixel , img->elemSize());
				card += img->elemSize(); 
				u += du;
				v += dv; 
				w += dw;
			} 
		}	
		else 
		{ 
			for (; width > 0;  width--)
			{ 
				if (w != 0) 
				{ 
					x = cfixed_div(u, w); 
					y = cfixed_div(v, w); 
				}	
				else 
				{  
					x = 0, y = 0; 
				} 

				s32 x0 = cfixed_to_int(x - cfixed_const_e); 
				s32 y0 = cfixed_to_int(y - cfixed_const_e); 

				ibitmap_fetch_pixel(img,&pixel,x0,y0);
				memcpy(card , &pixel , 3);
				card += img->elemSize(); 
				u += du;
				v += dv; 
				w += dw;
			} 
		} 
	}
	return 0;
}

typedef struct 
{
	s32 bottom;
	s32 top;
	s32 bottom_startx;
	s32 bottom_endx;
	s32 top_startx;
	s32 top_endx;
}VTrapeParam_t;

void inline ibitmap_Linearfill(u8* dst , u8* src , cfixed s , cfixed d)
{
	if (s > d)
	{
		cfixed step_x = cfixed_div(s,d);
		s32 d_int = cfixed_to_int(d);
		cfixed fixed_src = 0;
		for (s32 i = 0; i < d_int ; i++)
		{
			memcpy(dst , src + 3*cfixed_to_int(fixed_src) , 3 );
			fixed_src += step_x;
			dst += 3;
		}
	} 
	else
	{
		cfixed step_x = cfixed_div(d,s);
		s32 s_int = cfixed_to_int(s);
		s32 size = 3*cfixed_to_int(cfixed_ceil(step_x));
		cfixed fixed_dst = 0;

		for (s32 i = 0; i < s_int ; i++)
		{
			memcpy(dst +  3 * cfixed_to_int(fixed_dst), src  , size);
			fixed_dst += step_x;
			src += 3;
		}

	}

}
void ibitmap_HTrapetransform( Mat *dst,Mat *src,VTrapeParam_t *thiz)
{
	s32 bottom         = thiz->bottom;
	s32 top			   = thiz->top;
	s32 bottom_startx  = thiz->bottom_startx;
	s32 bottom_endx    = thiz->bottom_endx;
	s32 top_startx     = thiz->top_startx;
	s32 top_endx       = thiz->top_endx;

	u8* pSrcData = src->data;
	u8* pDstData = dst->data;
	u8* pSrc = src->data;
	u8* pDst = dst->data;

	cfixed starty_dst = cfixed_from_int(top);
	cfixed starty_src = cfixed_from_int(0);
	cfixed endy_dst   = cfixed_from_int(bottom);	
	cfixed endy_src   = cfixed_from_int(src->rows);
	cfixed y_dst      = starty_dst;
	cfixed y_src      = starty_src;
	cfixed startx_dst = cfixed_from_int(top_startx) ;
	cfixed endx_dst   = cfixed_from_int(top_endx) ;
	cfixed endx_src   = cfixed_from_int(src->cols);

	cfixed src_dy     = cfixed_div(endy_src - starty_src,endy_dst - starty_dst);
	cfixed dst_dx1    = cfixed_div(cfixed_from_int(bottom_startx - top_startx),cfixed_from_int(bottom - top));
	cfixed dst_dx2    = cfixed_div(cfixed_from_int(bottom_endx - top_endx),cfixed_from_int(bottom - top));

	while(y_dst < endy_dst && y_src < endy_src)
	{
		cfixed x_dst = startx_dst;
		cfixed x_src = 0;
		cfixed dx_src =  cfixed_div(endx_src ,endx_dst - startx_dst);

		pDst = pDstData + cfixed_to_int(y_dst)*dst->step + cfixed_to_int(startx_dst)*3;
		pSrc = pSrcData + cfixed_to_int(y_src)*src->step ;
	
		ibitmap_Linearfill(pDst , pSrc  , endx_src , endx_dst - startx_dst);

  		startx_dst += dst_dx1;
		endx_dst   += dst_dx2;
		y_dst += cfixed_const_1;
		y_src += src_dy ;
	}
}


s32 main()
{
	Mat src = imread("res_fish.bmp");
	imshow("Src" , src);

	//水平梯形变换
	Mat HTrapedst = Mat::zeros(600,800, CV_8UC3);    //创建目标图像
	VTrapeParam_t tParam = {0};
	tParam.bottom = 500;
	tParam.top = 100;
	tParam.top_startx = 200;
	tParam.top_endx = 350;
	tParam.bottom_startx = 10;
	tParam.bottom_endx = 600;
	ibitmap_HTrapetransform(&HTrapedst , &src , &tParam);
	imshow("HTrapedst" , HTrapedst);

	//任意四边形变换	
	Mat Quaddst = Mat::zeros(600,800, CV_8UC3);    //创建目标图像
	ipixel_point_fixed_t dstQuad[4] = {0};
	dstQuad[0].x = cfixed_from_int(10);  
	dstQuad[0].y = cfixed_from_int(70);  
	dstQuad[1].x = cfixed_from_int(200); 
	dstQuad[1].y = cfixed_from_int(230); 
	dstQuad[2].x = cfixed_from_int(250); 
	dstQuad[2].y = cfixed_from_int(100); 
	dstQuad[3].x = cfixed_from_int(130); 
	dstQuad[3].y = cfixed_from_int(20);  
	ibitmap_quadtransform(&Quaddst, &src,&dstQuad[0]);
	imshow("Quaddst" , Quaddst);

	s32 dst_Side_length = sqrt((float)src.cols*src.cols+(float)src.rows*src.rows)+1;
	s32 angle = 0;
	while (1)
	{
		++angle %= 360;
		Mat Rotatedst = Mat::zeros(dst_Side_length,dst_Side_length, CV_8UC3);    //创建目标图像
		ibitmap_rotate2D(&Rotatedst,&src,angle);
		imshow("Dstimage", Rotatedst);
		waitKey(40);
	}
}


                
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值