如何理解CGAffineTransform

CGAffineTransform

A structure for holding an affine transformation matrix.

以上是它的定义,其实就是一个矩阵的结构体,经常用于动画,形状变换。 包含如下参数:

struct CGAffineTransform { CGFloat a; CGFloat b; CGFloat c; CGFloat d; CGFloat tx; CGFloat ty; }; typedef struct CGAffineTransform CGAffineTransform;  

下面直观的描述这个这个矩阵和坐标之间的关系。

一个实验

  • 给一个UIImageView添加手势
    //zoom手势
    UIPinchGestureRecognizer* zoomer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(editImageWithZoom:)];
    
    UIRotationGestureRecognizer* rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(editImageWithRotation:)];
    [imageView addGestureRecognizer:zoomer];
    
    [imageView addGestureRecognizer:rotation];
  • 手势实现方法
//缩放
-(void)editImageWithZoom:(UIPinchGestureRecognizer*)sender
{
    CGAffineTransform transform= CGAffineTransformScale(originTransform, sender.scale, sender.scale);
    imageView.transform=transform;
}
//旋转
-(void)editImageWithRotation:(UIRotationGestureRecognizer*)sender
{
    CGAffineTransform transfrom = CGAffineTransformRotate(originTransform, sender.rotation);
    imageView.transform=transfrom;
}

其中的两个方法CGAffineTransformScaleCGAffineTransformRotate是生成旋转和缩放的矩阵,当然也可以直接使用通用方法

CGAffineTransform CGAffineTransformMake ( CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty );

生成对应的矩阵。

  • 继续变换

不修改任何代码,继续缩放和旋转。会发现每次都重新归位后旋转。 原来是CGAffineTransformIdentity这个常量搞的鬼。 每一次的rotatescale都是在这个常量的基础上变换的。

这个是它的定义。 解决这个问题只要在手势代码中加入

    if(sender.state==UIGestureRecognizerStateEnded || sender.state==UIGestureRecognizerStateCancelled)
    {
        //结束手势
        originTransform=imageView.transform;
    }

其中的originTransform可以定义为成员变量,初始化代码。

originTransform = CGAffineTransformIdentity;
  • 坐标变换之后出现的问题 意识到CGAffineTransform所做的变换其实是对坐标系做的变换。因此变换完以后使用平移操作会发现坐标系变换以后产生的影响。解决方案:
  • 取父view的坐标系,更改imageView.center,因为不论是scale还是rotationcenter的点是不变的。

获取变换后的参数

变换以后需要取得变换以后的scalerotation。 打变量观察。

(lldb) po transistion
 (a = 0.69003591274966281, b = -1.6204680103221447, c = 1.6204680103221447, d = 0.69003591274966281, tx = 0, ty = 0)  

其中scale是(双指缩放sx=sy):

rotation是:

联合作用在单位对角矩阵上:可以得到最终的transfrom:

可以解得: 好吧根本解不出来。另寻他路。

打算用成员变量接受每一次旋转和缩放后的参数。 打出每一次旋转和缩放操作的scalerotation。发现每一次都是重新从1和0开始计算。 于是简单了,在每一次手势结束的时候加上原来的参数。

-(void)editImageWithRotation:(UIRotationGestureRecognizer*)sender
{

    CGAffineTransform transfrom = CGAffineTransformRotate(originTransform, sender.rotation);
    imageView.transform=transfrom;
   // NSLog(@"%lf",sender.rotation);
    if(sender.state==UIGestureRecognizerStateEnded || sender.state==UIGestureRecognizerStateCancelled)
    {
        //结束手势
        radians = radians+sender.rotation;
        originTransform=imageView.transform;
    }
}

scale类似方法获得。 输出最后imageViewframe和最开始的frame

frame = (247.357 307.2; 273.285 409.6)  //最初的
frame = (142.016 271.144; 483.968 481.711)  //变换后的
r = 0.79710480433663233  //旋转参数

swift的牛逼的playground下调试

let r = 0.79710480433663233
let w = 273.285
let h = 409.6
let nw = h*cos(r)+w*sin(r)
let nh = h*sin(r)+w*cos(r)

发现rect旋转后的rect其实是这样:

所以要获取用户变换以后的图片,可以这么来。

    UIImage* editedImge = [image imageByScalingToSize:CGSizeMake(originRect.size.width*scale, originRect.size.height*scale)];
    editedImge = [editedImge imageRotatedByRadians:rotation];
    
    //获取最终点的坐标
    [editedImge drawInRect:rect];

大功告成。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏章鱼的慢慢技术路

OpenGL基本框架与三维对象绘制

17520
来自专栏落影的专栏

GPUImage详细解析(三)- 实时美颜滤镜

回顾 解析(一) 解析(二) GPUImageFilter就是用来接收源图像,通过自定义的顶点、片元着色器来渲染新的图像,并在绘制完成后通知响应链的下一个对...

65250
来自专栏素质云笔记

python︱利用dlib和opencv实现简单换脸、人脸对齐、关键点定位与画图

这是一个利用dlib进行关键点定位 + opencv处理的人脸对齐、换脸、关键点识别的小demo。原文来自于《Switching Eds: Face swapp...

2K100
来自专栏贾志刚-OpenCV学堂

手撕OpenCV源码之高斯模糊

从上述代码的大致分析中可以知道,OpenCV的GaussianBlur本质上依然是filter2D,只是针对一些特殊情况进行了GPU和CPU版本的优化,如果输入...

34720
来自专栏诸葛青云的专栏

Python识别验证码!学会这步,百分之60的网站你基本都能识别了!

127是我们设定的阈值,像素值大于127被置成了0,小于127的被置成了255。处理后的图片变成了这样

14800
来自专栏北京马哥教育

Kmeans聚类代码实现及优化

云豆贴心提醒,本文阅读时间6分钟 这篇文章直接给出上次关于Kmeans聚类的篮球远动员数据分析案例,最后介绍Matplotlib包绘图的优化知识。 希望这篇文...

36350
来自专栏Python小屋

Python绘制渐变色三角形

本文要点在于Python扩展库pyopengl的应用,关于OpenGL函数参数含义可以查阅有关资料。 import sys from OpenGL.GL imp...

41660
来自专栏Python小屋

Python绘制三次贝塞尔曲线

对于贝塞尔曲线而言,其特点在于第一个控制点恰好是曲线的起点,最后一个控制点是曲线的终点,其他控制点并不在曲线上,而是起到控制曲线形状的作用。另外,曲线的起点处与...

77860
来自专栏一“技”之长

iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间

    颜色的实质是表示颜色的二进制数据,如果没有确定的规则,则这些二进制数据完全没有意义。所谓色彩空间,即是表示这些颜色数据信息是如何解释的。同样的一张图片,...

12130
来自专栏AI研习社

Github 项目推荐 | 无监督神经机器翻译 —— UNdreaMT

UNdreaMT 是一个开源的无监督神经机器翻译系统,该系统的具体实现方式在以下的论文里有详细地描述:

17420

扫码关注云+社区

领取腾讯云代金券