iPhone图像拉伸(歪斜) [英] iPhone image stretching (skew)

查看:155
本文介绍了iPhone图像拉伸(歪斜)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何扭曲图像?例如,每个角都有一个带有坐标的CGPoint - p1,p2,p3,p4。然后,我需要设置 - p4.x + = 50,p4.y + = 30。所以这个角(p4)应该在2D透视图中拉伸,图像应该扭曲。

How do I skew an image? For example, each corner has a CGPoint with coords - p1, p2, p3, p4. Then, I need to set - p4.x+=50, p4.y+=30. So this corner (p4) should be stretched in a 2D perspective and the image should be distorted.

替代文字http://www.polar-b.com/scew.png

我试图使用 CATransform3D ,但似乎不能以这种方式完成,因为它只是改变了视角(旋转,更靠近/更远一侧)。也许 CGAffineTransform 可能有用吗?

I tried to use CATransform3D, but it seems that this cannot be done in such way, since it's only a change the perspective of view (rotate, bring closer/farther one side). Maybe CGAffineTransform can be useful?

如果你知道答案,请写一个示例代码。

If you know the answer, please write a sample code.

提前致谢

推荐答案

CGAffineTransform无法实现。仿射变换总是可以分解为平移,旋转,剪切和缩放。它们都将平行四边形映射成平行四边形,而变换则不然。

Not possible with CGAffineTransform. An affine transform can always be decomposed into translations, rotations, shearing and scaling. They all map parallelograms into parallelograms, which your transform does not.

对于变换,可以分两步完成。一个将方块转换为梯形。

For your transform, it can be done in two steps. One to convert the square into a trapezoid.

p1-----p2       p1-----p2
 |     |   -->   |       \
p3-----p4       p3--------p4'

另一个垂直方向。天真的转换规则是

Another to the vertical direction. A naive transformation rule is

                   y - c
x' = (x - p1.x) * ———————— + p1.x
                  p1.y - c
y' = y

其中c是连接p1和p3以及p2和p4的线的交点的y坐标。

where c is the y-coordinate of the intersection point of the lines joining p1 and p3, and p2 and p4.

现在注意x * y转型中的因素。这表明这种变换是线性的。因此,CATransform3D也不能将其作为2D变换执行。

Now notice the x*y factor in the transformation. This indicates such a transform is not linear. Therefore, CATransform3D cannot perform this as a 2D transform either.

但是,向量

[x, y, z, w=1]

将转换为实际的3D矢量

will be converted to the actual 3D vector

(x/w, y/w, z/w)


如果CA遵循通常的3D计算图形规则,则在投影前

,因此您可以通过使用转换来欺骗

before projection if CA follows usual 3D compute graphics rules, so you could "cheat" by using the transform

[ P . . Q ] [ x ]   [ x' ]
[ . R . S ] [ y ] = [ y' ]
[ . . 1 . ] [ z ]   [ z' ]
[ . T . U ] [ 1 ]   [ w' ]

有适当的P,Q,R,S,T, U将4个点映射到预期位置。 (6个唯一坐标和6个变量在大多数情况下应该只有1个解。)

with appropriate P, Q, R, S, T, U that maps the 4 points to the expected locations. (6 unique coordinates and 6 variables should have exactly 1 solution most of the cases.)

当你找到这6个常数时,你可以制作一个 CATransform3D 。注意结构定义是

When you have found these 6 constants, you can craft a CATransform3D. Notice the structure definition is

struct CATransform3D
   {
   CGFloat m11, m12, m13, m14;
   CGFloat m21, m22, m23, m24;
   CGFloat m31, m32, m33, m34;
   CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;

因此,您可以直接更改矩阵元素,而不是依赖于CATransform3DMake函数。 (由于使用行或列向量的惯例,您可能需要执行转置。)

So you can directly change the matrix elements, instead of relying on the CATransform3DMake functions. (You may need to perform a transpose due to convention of using row or column vectors.)

要获得转换为将矩形((X,Y),(W,H))转换为任何四边形((x1a,y1a),(x2a,y2a);(x3a,y3a),(x4a,y4a)),使用此函数(你)可能需要转置):

To obtain the transform to convert a rectangle ((X, Y), (W, H)) to any quadrilateral ((x1a, y1a), (x2a, y2a); (x3a, y3a), (x4a, y4a)), use this function (you may need a transpose):

function compute_transform_matrix(X, Y, W, H, x1a, y1a, x2a, y2a, x3a, y3a, x4a, y4a) {
    var y21 = y2a - y1a, 
        y32 = y3a - y2a,
        y43 = y4a - y3a,
        y14 = y1a - y4a,
        y31 = y3a - y1a,
        y42 = y4a - y2a;

    var a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42);
    var b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);
    var c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43);

    var d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a);
    var e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42);
    var f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a)));

    var g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43);
    var h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42);
    var i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a));

    return [[a,b,0,c],[d,e,0,f],[0,0,1,0],[g,h,0,i]];
}

这篇关于iPhone图像拉伸(歪斜)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆