CGAffineTransformMake 矩阵变换 的运算原理

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;

caseUIImageOrientationRightMirrored:

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:

[NSExceptionraise: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 矩阵变换 的运算原理

时间: 2024-10-12 13:37:04

CGAffineTransformMake 矩阵变换 的运算原理的相关文章

图像处理之基础---二维卷积运算原理剖析

卷积运算(Convolution)是通过两个函数f 和g 生成第三个函数的一种数学算子,表示函数f 与经过翻转和平移与g 的重叠部分的累积.如果将参加卷积的一个函数看作区间的指示函数,卷积还可以被看作是“滑动平均”的推广.假设: f(x),g(x)是R1上的两个可积函数,并且积分是存在的.这样,随着 x 的不同取值,这个积分就定义了一个新函数h(x),称为函数f 与g 的卷积,记为h(x)=(f*g)(x). 两个向量卷积,说白了就是多项式乘法.下面用个矩阵例子说明其工作原理: a和d的卷积就是

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

下面是将byte数组转换为float的实现 public static float getFloat(byte[] b) { int accum = 0; accum = accum|(b[0] & 0xff) << 0; accum = accum|(b[1] & 0xff) << 8; accum = accum|(b[2] & 0xff) << 16; accum = accum|(b[3] & 0xff) << 24;

程序员必知之浮点数运算原理详解

导读:浮点数运算是一个非常有技术含量的话题,不太容易掌握.许多程序员都不清楚使用==操作符比较float/double类型的话到底出现什么问题. 许多人使用float/double进行货币计算时经常会犯错.这篇文章是这一系列中的精华,所有的软件开发人员都应该读一下. 随着你经验的增长,你肯定 想去深入了解一些常见的东西的细节,浮点数运算就是其中之一. 1. 什么是浮点数? 在计算机系统的发展过程中,曾经提出过多种方法表达实数. [1]典型的比如相对于浮点数的定点数(Fixed Point Num

【转载】程序员必知之浮点数运算原理详解

https://blog.csdn.net/tercel_zhang/article/details/52537726 导读:浮点数运算是一个非常有技术含量的话题,不太容易掌握.许多程序员都不清楚使用==操作符比较float/double类型的话到底出现什么问题. 许多人使用float/double进行货币计算时经常会犯错.这篇文章是这一系列中的精华,所有的软件开发人员都应该读一下. 随着你经验的增长,你肯定 想去深入了解一些常见的东西的细节,浮点数运算就是其中之一. 1. 什么是浮点数? 在计

Java位运算原理及使用讲解

前言日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法.举个例子,翻转操作比较常见,比如初始值为1,操作一次变为0,再操作一次变为1.可能的做法是使用三木运算符,判断原始值为1还是0,如果是1,设置为0,否则设置为0.但是使用位运算,不用判断原始值,直接改变值就可以: 1^num//num为原始值 当然,一条语句可能对代码没什么影响,但是在高重复,大数据量的情况下将会节省很多开销. 以下是自己整理的关于java位运算的部分内容,如有错误,还请指出,以共同进步,先行致谢

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

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),用来作为坐

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

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

1. 为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(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 

Java语法基础--运算

常量是一些不变的数据,我们用变量的方式把常量给记录下来,变量是内存中一个空间,空间中可以存储某些类型的数据,变量还有一个好处,就是可以给一些常量取名称,方便阅读: 取模运算 就是取余数.模2运算,非0即1,用于切换. -3%6结果是-3 . 3%-6结果是3 . 负数运算参考左边符号. 对于除号"/",它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分. 例如:int x=3510;x=x/1000*1000;  x的结果是3. 自增运算 ++ int a=3