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的矩阵运算的例子,无外乎是运用以上三种变换的组合,达到所定义的效果:

  1. //UIImageOrientation的定义,定义了如下几种变换
  2. typedef enum
  3. {
  4. UIImageOrientationUp,            // default orientation
  5. UIImageOrientationDown,          // 180 deg rotation
  6. UIImageOrientationLeft,          // 90 deg CCW
  7. UIImageOrientationRight,         // 90 deg CW
  8. UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
  9. UIImageOrientationDownMirrored,  // horizontal flip
  10. UIImageOrientationLeftMirrored,  // vertical flip
  11. UIImageOrientationRightMirrored, // vertical flip
  12. } UIImageOrientation;
  13. //按照UIImageOrientation的定义,利用矩阵自定义实现对应的变换;
  14. -(UIImage *)transformImage:(UIImage *)aImage
  15. {
  16. CGImageRef imgRef = aImage.CGImage;
  17. CGFloat width = CGImageGetWidth(imgRef);
  18. CGFloat height = CGImageGetHeight(imgRef);
  19. CGAffineTransform transform = CGAffineTransformIdentity;
  20. CGRect bounds = CGRectMake(0, 0, width, height);
  21. CGFloat scaleRatio = 1;
  22. CGFloat boundHeight;
  23. UIImageOrientation orient = aImage.imageOrientation;
  24. switch(UIImageOrientationLeftMirrored)
  25. {
  26. case UIImageOrientationUp:
  27. transform = CGAffineTransformIdentity;
  28. break;
  29. case UIImageOrientationUpMirrored:
  30. transform = CGAffineTransformMakeTranslation(width, 0.0);
  31. transform = CGAffineTransformScale(transform, -1.0, 1.0);
  32. break;
  33. case UIImageOrientationDown:
  34. transform = CGAffineTransformMakeTranslation(width, height);
  35. transform = CGAffineTransformRotate(transform, M_PI);
  36. break;
  37. case UIImageOrientationDownMirrored:
  38. transform = CGAffineTransformMakeTranslation(0.0, height);
  39. transform = CGAffineTransformScale(transform, 1.0, -1.0);
  40. break;
  41. case UIImageOrientationLeft:
  42. boundHeight = bounds.size.height;
  43. bounds.size.height = bounds.size.width;
  44. bounds.size.width = boundHeight;
  45. transform = CGAffineTransformMakeTranslation(0.0, width);
  46. transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
  47. break;
  48. case UIImageOrientationLeftMirrored:
  49. boundHeight = bounds.size.height;
  50. bounds.size.height = bounds.size.width;
  51. bounds.size.width = boundHeight;
  52. transform = CGAffineTransformMakeTranslation(height, width);
  53. transform = CGAffineTransformScale(transform, -1.0, 1.0);
  54. transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
  55. break;
  56. case UIImageOrientationRight: //EXIF = 8
  57. boundHeight = bounds.size.height;
  58. bounds.size.height = bounds.size.width;
  59. bounds.size.width = boundHeight;
  60. transform = CGAffineTransformMakeTranslation(height, 0.0);
  61. transform = CGAffineTransformRotate(transform, M_PI / 2.0);
  62. break;
  63. case UIImageOrientationRightMirrored:
  64. boundHeight = bounds.size.height;
  65. bounds.size.height = bounds.size.width;
  66. bounds.size.width = boundHeight;
  67. transform = CGAffineTransformMakeScale(-1.0, 1.0);
  68. transform = CGAffineTransformRotate(transform, M_PI / 2.0);
  69. break;
  70. default:
  71. [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
  72. }
  73. UIGraphicsBeginImageContext(bounds.size);
  74. CGContextRef context = UIGraphicsGetCurrentContext();
  75. if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
  76. CGContextScaleCTM(context, -scaleRatio, scaleRatio);
  77. CGContextTranslateCTM(context, -height, 0);
  78. }
  79. else {
  80. CGContextScaleCTM(context, scaleRatio, -scaleRatio);
  81. CGContextTranslateCTM(context, 0, -height);
  82. }
  83. CGContextConcatCTM(context, transform);
  84. CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
  85. UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
  86. UIGraphicsEndImageContext();
  87. return imageCopy;
  88. }

掌握矩阵运算的原理,对视图的矩阵操作便会得心应手,巧妙利用旋转,平移,缩放,组合起来达到你所想要的变换效果!

从UIImage的矩阵变换看矩阵运算的原理的更多相关文章

  1. CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理

    简记: CGAffineTransformMake(a,b,c,d,tx,ty) ad缩放bc旋转tx,ty位移,基础的2D矩阵 公式 x=ax+cy+tx    y=bx+dy+ty 1.矩阵的基本 ...

  2. CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理 (转载)

    简记: CGAffineTransformMake(a,b,c,d,tx,ty) ad缩放bc旋转tx,ty位移,基础的2D矩阵 公式 x=ax+cy+tx     y=bx+dy+ty 1.矩阵的基 ...

  3. Struts1——离BeanUtils看struts其原理1

    在Struts中非常典型的特点就是使用了ActionForm来搜集表单数据,可是搜集到的表单数据所有都是String类型的.假设我们直接拿来使用我们会面临一个非常麻烦的问题就是频繁的类型装换. Str ...

  4. 从JDK源码角度看线程池原理

    "池"技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实 ...

  5. 第6月第17天 CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理

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

  6. 源代码看CoordinatorLayout.Behavior原理

    在上一篇博客CoordinatorLayout高级使用方法-自己定义Behavior中,我们介绍了怎样去自己定义一个CoordinatorLayout的Behavior.通过文章也能够看出Behavi ...

  7. 从SpringBoot源码看资源映射原理

    前言 很多的小伙伴刚刚接触SpringBoot的时候,可能会遇到加载不到静态资源的情况. 比如html没有样式,图片无法加载等等. 今天王子就与大家一起看看SpringBoot中关于资源映射部分的主要 ...

  8. 从Select语句看Oracle查询原理(了解Oracle的查询机制)

    第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,他的主 ...

  9. 窥看 SpringBoot 的原理与使用

    一:SpringBoot的启动 1. 继承spring-boot-starter-parent项目 2. 导入spring-boot-dependencies项目依赖 二:Spring Boot 主类 ...

随机推荐

  1. shell 变量自增(转)

    原文地址:http://www.cnblogs.com/iloveyoucc/archive/2012/07/11/2585559.html Linux Shell中写循环时,常常要用到变量的自增,现 ...

  2. Linux学习之十二、命令别名与历史命令

    命令别名配置: alias, unalias 那么需要下达『 ls -al | more 』这个命令,我是觉得很烦啦! 要输入好几个单字!那可不可以使用 lm 来简化呢?当然可以,你可以在命令行下面下 ...

  3. document.body.scrollTop与document.documentElement.scrollTop兼容

    这两天在写一个JS的网页右键菜单,在实现菜单定位的时候发现了这个问题:chrome居然不认识document.documentElement.scrollTop! 看前辈们的文章,纷纷表示如果有文档声 ...

  4. Mongo散记--聚合(aggregation)& 查询(Query)

    mongo官网:http://www.mongodb.org/ 工作中使用到Mongo,可是没有系统的学习研究过Mongo,仅对工作过程中,在Mongo的使用过程中的一些知识点做一下记录,并随时补充, ...

  5. C#语言小结

    数据类型--变量与常量--运算符与表达式--语句(if,for)--数组--函数--结构体 一.数据类型:(一)内建类型整型(int short long byte uint ushort ulong ...

  6. Mina入门:Java NIO基础概念

    JDK1.4引入了Java NIO API(Java New IO),Java NIO得到了广泛应用.NIO允许程序进行非阻塞IO操作.java.nio.* 包括以下NIO基本结构: Buffer - ...

  7. asp.net 连接sqlserver数据库

    在asp.net中连接sqlserver数据库之前,首先得确保正常安装了sqlserver2008,同时有数据库. 在项目中添加一个类DB,用来专门负责执行对数据库的增删改查.在添加的过程中会弹出下面 ...

  8. MOSS2010部署解决方案失败是可以尝试更新

    update-spsolution -identity XXX.wsp -literalpath D:\SPS2010Setup\XXX.wsp -gacdeployment

  9. HTML5实现坦克大战(一)

      Tank 字段 x:坦克的中心点的横坐标 y:坦克的中心点的纵坐标 dir:坦克的前进的方向 spped:坦克的速度 color:坦克的颜色,用于区分种类不同的坦克 bullet:坦克的子弹 为a ...

  10. SQL Server数据库---》基础

    SQL Server:只是操作数据库的一个工具(这种工具,只是提供一个界面化的方式让用户方便操作数据库) 开启服务:点击:我的电脑(计算机)--管理--服务和应用程序--服务--开启SQL Serve ...