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.矩阵的基本知识:
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); //沿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, 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(a,b,c,d,tx,ty) 矩阵运算的原理的更多相关文章
- 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.矩阵的基 ...
- 第6月第17天 CGAffineTransformMake(a,b,c,d,tx,ty) 矩阵运算的原理
1. 为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准.所以所有的变化都由前两列完成. 以上参数在矩阵中 ...
- 从UIImage的矩阵变换看矩阵运算的原理
1.矩阵的基本知识: struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty;}; CGAffineTransform CGAf ...
- CGAffineTransformMake 矩阵变换 的运算原理(转)
1.矩阵的基本知识: struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty; }; CGAffineTransform CGAff ...
- IOS-CGAffineTransformMake 矩阵变换 的运算原理
1.矩阵的基本知识: struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty; }; CGAffineTransform C ...
- transform初学习
1.什么是transform? transform主要用于形变,位移和旋转,可用于动画. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: jus ...
- iOS:动画(18-10-15更)
目录 1.UIView Animation 1-1.UIView Animation(基本使用) 1-2.UIView Animation(转场动画) 2.CATransaction(Layer版的U ...
- 关于opengl中的矩阵平移,矩阵旋转,推导过程理解 OpenGL计算机图形学的一些必要矩阵运算知识
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12166896.html 为什么引入齐次坐标的变换矩阵可以表示平移呢? - Yu Mao的回答 ...
- UIView的动画之初步学习
animateWithDuration:<#(NSTimeInterval)#> delay:<#(NSTimeInterval)#> options:<#(UIView ...
随机推荐
- Linux统计某文件夹下文件、文件夹的个数
统计某文件夹下文件的个数 ls -l |grep "^-"|wc -l 统计某文件夹下目录的个数 ls -l |grep "^d"|wc -l 统计文件夹下文件 ...
- hdu 1560 DNA sequence(搜索)
http://acm.hdu.edu.cn/showproblem.php?pid=1560 DNA sequence Time Limit: 15000/5000 MS (Java/Others) ...
- 学习lamda表达式
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.L ...
- Asynchronous socket communication
来源:http://www.codeproject.com/Articles/1608/Asynchronous-socket-communication 本地下载 Download source f ...
- Logback 将日志分级别打印
最近项目中用到了logback 记录日志, 关于为啥使用logback 请百度一下: logback与Log4J的区别 好了,废话不多说,直奔主题, 研究了好久,终于将日志按级别将日志分文件打印出 ...
- matlab怎么同时显示imshow 两幅图片
matlab怎么同时显示imshow 两幅图片 matlab怎么同时显示imshow 两幅图片 方法一:subplot()函数 subplot(2,1,1); subplot(2,1,2); 分上下或 ...
- php和.net的DES加密解密方法
.net版本 /// <summary> /// DES加密 /// </summary> /// <param name="pToEncrypt"& ...
- 练习-libev和pyev示例
事件循环,IO复用,还是理解深刻一点好. 比较LIBEV和PYEV,发现PYTHON库只是对LIBEV作了简单的语法转换. 到了这个层次,就一个字:DIAO!!! libev的C版: #include ...
- 严重: The web application [] registered the JDBC driver 错误
近日发现启动tomcat的时候报如下警告: -- :: org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc 严重: The ...
- SQLite入门与分析(八)---存储模型(2)
3.页面结构(page structure) 数据库文件分成固定大小的页面.SQLite通过B+tree模型来管理所有的页面.页面(page)分三种类型:要么是tree page,或者是overflo ...