简记:

CGAffineTransformMake(a,b,c,d,tx,ty)

ad缩放bc旋转tx,ty位移,基础的2D矩阵

公式

x=ax+cy+tx
    y=bx+dy+ty

1.矩阵的基本知识:

struct CGAffineTransform

{
  CGFloat a, b, c, d;
  CGFloat tx, ty;
};

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

为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准。所以所有的变化都由前两列完成。

以上参数在矩阵中的表示为:

|a    b    0|

|c    d    0|

|tx   ty   1|

运算原理:原坐标设为(X,Y,1);

|a    b    0|

[X,Y,  1]      |c    d    0|     =     [aX + cY + tx   bX + dY + ty  1] ;

|tx    ty  1|

通过矩阵运算后的坐标[aX + cY + tx   bX + dY + ty  1],我们对比一下可知:

第一种:设a=d=1, b=c=0.  

[aX + cY + tx   bX + dY + ty  1] = [X  + tx  Y + ty  1];

可见,这个时候,坐标是按照向量(tx,ty)进行平移,其实这也就是函数

CGAffineTransform CGAffineMakeTranslation(CGFloat tx,CGFloat ty)的计算原理。

第二种:设b=c=tx=ty=0.  

[aX + cY + tx   bX + dY + ty  1] = [aX    dY   1];

可见,这个时候,坐标X按照a进行缩放,Y按照d进行缩放,a,d就是X,Y的比例系数,其实这也就是函数

CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)的计算原理。a对应于sx,d对应于sy。

第三种:设tx=ty=0,a=cosɵ,b=sinɵ,c=-sinɵ,d=cosɵ。

[aX + cY + tx   bX + dY + ty  1] = [Xcosɵ - Ysinɵ    Xsinɵ + Ycosɵ  1] ;

可见,这个时候,ɵ就是旋转的角度,逆时针为正,顺时针为负。其实这也就是函数

CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)的计算原理。angle即ɵ的弧度表示。

2.利用上面的变换写一个UIImage矩阵变换的例子:

下面是一个关于image的矩阵运算的例子,无外乎是运用以上三种变换的组合,达到所定义的效果

 //UIImageOrientation的定义,定义了如下几种变换
typedef enum
{
UIImageOrientationUp, // default orientation UIImageOrientationDown, // 180 deg rotation UIImageOrientationLeft, // 90 deg CCW UIImageOrientationRight, // 90 deg CW UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip UIImageOrientationDownMirrored, // horizontal flip UIImageOrientationLeftMirrored, // vertical flip UIImageOrientationRightMirrored, // vertical flip } UIImageOrientation; //按照UIImageOrientation的定义,利用矩阵自定义实现对应的变换; -(UIImage *)transformImage:(UIImage *)aImage { CGImageRef imgRef = aImage.CGImage; CGFloat width = CGImageGetWidth(imgRef); CGFloat height = CGImageGetHeight(imgRef); CGAffineTransform transform = CGAffineTransformIdentity; CGRect bounds = CGRectMake(, , width, height); CGFloat scaleRatio = ; CGFloat boundHeight; UIImageOrientation orient = aImage.imageOrientation; switch(UIImageOrientationLeftMirrored) { case UIImageOrientationUp: transform = CGAffineTransformIdentity; break; case UIImageOrientationUpMirrored: transform = CGAffineTransformMakeTranslation(width, 0.0); transform = CGAffineTransformScale(transform, -1.0, 1.0); //沿y轴向左翻 break; case UIImageOrientationDown:
transform = CGAffineTransformMakeTranslation(width, height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationDownMirrored: transform = CGAffineTransformMakeTranslation(0.0, height); transform = CGAffineTransformScale(transform, 1.0, -1.0); break; case UIImageOrientationLeft: boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(0.0, width); transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); break; case UIImageOrientationLeftMirrored: boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(height, width); transform = CGAffineTransformScale(transform, -1.0, 1.0); transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); break; case UIImageOrientationRight: //EXIF = 8 boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(height, 0.0); transform = CGAffineTransformRotate(transform, M_PI / 2.0); break; case UIImageOrientationRightMirrored: boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeScale(-1.0, 1.0); transform = CGAffineTransformRotate(transform, M_PI / 2.0); break; default: [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; } UIGraphicsBeginImageContext(bounds.size); CGContextRef context = UIGraphicsGetCurrentContext(); if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { CGContextScaleCTM(context, -scaleRatio, scaleRatio); CGContextTranslateCTM(context, -height, ); } else { CGContextScaleCTM(context, scaleRatio, -scaleRatio); CGContextTranslateCTM(context, , -height); } CGContextConcatCTM(context, transform); CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(, , width, height), imgRef); UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy; }

借鉴: https://developer.apple.com/library/ios/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_affine/dq_affine.html

最新文章

  1. 基于shell脚本比较数字加减乘除
  2. Jquery和Javascript 实际项目中写法基础-ajax和json (3)
  3. salesforce 零基础学习(十七)Trigger用法
  4. Xamarin.Android开发实践(十六)
  5. Pipe(点积叉积的应用POJ1039)
  6. VMware虚拟系统 bridged、NAT、host-only三种网络连接模式
  7. 从linux内核代码分析操作系统启动过程
  8. jQuery 源码分析3: jQuery.fn/ jQuery.prototype
  9. Unity3d 与IOS 相互调用
  10. 读jquery.cookie.js源码学到的几个技巧
  11. JavaEE中的MVC(二)Xml配置实现IOC控制反转
  12. ConcurrenHashMap源码分析(二)
  13. 抓取Android应用的log
  14. AOP事务解决方案和分布式事务方案
  15. 常用邮箱POP3 STMP服务器与端口号设置
  16. register关键字
  17. mybatis 中使用oracle merger into
  18. button中文字垂直居中
  19. JDBC插入数据超长时无法自动截断问题
  20. 四道腾讯的javascript面试题

热门文章

  1. cURL.1 手册页
  2. oracle的内存管理(之中的一个)
  3. Linux下卸载ORACLE的多种方法(转)
  4. 自动工作负载库(Automatic Workload Repository,AWR)
  5. poj 2431
  6. Knime 使用 初探
  7. zepto 获取checked selected元素
  8. CentOS上编译安装Git
  9. 前端开发面试题收集 JS
  10. JavaScript处理HTML DOM