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(0, 0, width, height); CGFloat scaleRatio = 1; 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); 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, 0); } else { CGContextScaleCTM(context, scaleRatio, -scaleRatio); CGContextTranslateCTM(context, 0, -height); } CGContextConcatCTM(context, transform); CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy; }

CGAffineTransformMake 矩阵变换 的运算原理(转)的更多相关文章

  1. IOS-CGAffineTransformMake 矩阵变换 的运算原理

    1.矩阵的基本知识: struct CGAffineTransform {   CGFloat a, b, c, d;   CGFloat tx, ty; }; CGAffineTransform C ...

  2. byte数组转float实现与byte转换其它类型时进行&运算原理

    下面是将byte数组转换为float的实现 public static float getFloat(byte[] b) { int accum = 0; accum = accum|(b[0] &a ...

  3. 2-12 tensorflow运算原理

    #opencv tensorflow #类比 语法 api 原理 #基础数据类型 运算符 流程 字典 数组 import tensorflow as tf #data1 = tf.constant(2 ...

  4. Java位运算原理及使用讲解

    前言日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法.举个例子,翻转操作比较常见,比如初始值为1,操作一次变为0,再操作一次变为1.可能的做法是使用三木运算符,判断原始值 ...

  5. spark提交运算原理

    前面几天元旦过high了,博客也停了一两天,哈哈,今天我们重新开始,今天我们介绍的是spark的原理 首先先说一个小贴士: spark中,对于var count = 0,如果想使count自增,我们不 ...

  6. 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.矩阵的基本 ...

  7. 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.矩阵的基 ...

  8. 从UIImage的矩阵变换看矩阵运算的原理

    1.矩阵的基本知识: struct CGAffineTransform {  CGFloat a, b, c, d;  CGFloat tx, ty;}; CGAffineTransform CGAf ...

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

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

随机推荐

  1. 研究ecmall一些流程、结构笔记 (转)

    index.phpECMall::startup() //ecmall.php object //所有类的基础类 ecmall.phpBaseApp //控制器基础类 app.base.phpECBa ...

  2. 20 几个知名公司的 Java 面试题汇总

    查看不同公司新鲜真实的Java面试题,摘自Glassdoor.com 巴克莱投资: 假设有一个 getNextparson() 方法返回 Person 对象,Person 类实现了 comparabl ...

  3. Linux命令 改变文档权限及所有者

    Linux命令 改变文档权限及所有者 chgrp :改变档案所属群组 chown :改变档案拥有者 chmod :改变档案的权限, SUID, SGID, SBIT等等的特性 chgrp说明及范例 [ ...

  4. 机器学习(Machine Learning)&深度学习(Deep Learning)资料(下)

    转载:http://www.jianshu.com/p/b73b6953e849 该资源的github地址:Qix <Statistical foundations of machine lea ...

  5. emacs之开始就加载tag

    ~/emacsConfig/original-tags.el (setq tags-table-list ' ( "~/emacsConfig/etags/muduo" " ...

  6. idea之jrebel热部署使用教程

    JRebel是一个J2EE热部署的工具.使用它可以减少浪费8-18%的开发时间在项目的构建和部署上.虽然Java也提供了HotSpot的JVM,但是如果你修改的类中有方法名称变动的话,HotSpot就 ...

  7. mysql 存储过程简单学习

    转载自:http://blog.chinaunix.net/uid-23302288-id-3785111.html ■存储过程Stored Procedure 存储过程就是保存一系列SQL命令的集合 ...

  8. SQLserver2008全文检索使用方法

    一.开启SQL Full-text服务: 保证 SQL Full-text Filter Daemon Launcher服务处于开启状态,不同版本SQLServer全文检索服务名称可能稍有不同,如果服 ...

  9. preprocess

    1,宏定义,有参宏,无参宏,宏定义实现的是定义一个符号常量; 条件编译3种方式,文件包含含义; 不带参数的宏定义;既用一个指定的的标识符来代替一个字符串; #define RUIY 10000000 ...

  10. Java的native关键字以及JNI

    http://blog.csdn.net/yangjiali014/article/details/1633017 这篇博文相当清楚了 包括native关键字的介绍,JNI的书写步骤,以及JNI的实现 ...