#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);
}
}
图片任意角度旋转 梯形变换 任意四边形变换
最新推荐文章于 2022-12-29 17:10:56 发布