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

  1 //UIImageOrientation的定义,定义了如下几种变换  
  2 typedef enum   
  3 {  
  4     UIImageOrientationUp,            // default orientation  
  5   
  6    UIImageOrientationDown,          // 180 deg rotation  
  7   
  8    UIImageOrientationLeft,          // 90 deg CCW  
  9       
 10     UIImageOrientationRight,         // 90 deg CW  
 11       
 12     UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip  
 13       
 14     UIImageOrientationDownMirrored,  // horizontal flip  
 15       
 16     UIImageOrientationLeftMirrored,  // vertical flip  
 17       
 18     UIImageOrientationRightMirrored, // vertical flip  
 19   
 20 } UIImageOrientation;  
 21   
 22 //按照UIImageOrientation的定义,利用矩阵自定义实现对应的变换;  
 23   
 24 -(UIImage *)transformImage:(UIImage *)aImage    
 25   
 26 {    
 27   
 28     CGImageRef imgRef = aImage.CGImage;    
 29       
 30     CGFloat width = CGImageGetWidth(imgRef);    
 31       
 32     CGFloat height = CGImageGetHeight(imgRef);    
 33        
 34     CGAffineTransform transform = CGAffineTransformIdentity;    
 35       
 36     CGRect bounds = CGRectMake(0, 0, width, height);    
 37          
 38     CGFloat scaleRatio = 1;    
 39          
 40     CGFloat boundHeight;    
 41       
 42     UIImageOrientation orient = aImage.imageOrientation;    
 43       
 44     switch(UIImageOrientationLeftMirrored)    
 45       
 46     {    
 47               
 48         case UIImageOrientationUp:    
 49               
 50             transform = CGAffineTransformIdentity;  
 51   
 52             break;    
 53                          
 54         case UIImageOrientationUpMirrored:   
 55               
 56             transform = CGAffineTransformMakeTranslation(width, 0.0);    
 57               
 58             transform = CGAffineTransformScale(transform, -1.0, 1.0); //沿y轴向左翻   
 59               
 60             break;    
 61                          
 62         case UIImageOrientationDown:              
 63             transform = CGAffineTransformMakeTranslation(width, height);    
 64               
 65             transform = CGAffineTransformRotate(transform, M_PI);    
 66               
 67             break;    
 68                          
 69         case UIImageOrientationDownMirrored:   
 70               
 71             transform = CGAffineTransformMakeTranslation(0.0, height);    
 72               
 73             transform = CGAffineTransformScale(transform, 1.0, -1.0);    
 74               
 75             break;    
 76                         
 77         case UIImageOrientationLeft:     
 78               
 79             boundHeight = bounds.size.height;    
 80               
 81             bounds.size.height = bounds.size.width;    
 82               
 83             bounds.size.width = boundHeight;    
 84               
 85             transform = CGAffineTransformMakeTranslation(0.0, width);    
 86               
 87             transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);    
 88               
 89             break;  
 90                          
 91         case UIImageOrientationLeftMirrored:     
 92               
 93             boundHeight = bounds.size.height;    
 94               
 95             bounds.size.height = bounds.size.width;    
 96               
 97             bounds.size.width = boundHeight;    
 98               
 99             transform = CGAffineTransformMakeTranslation(height, width);    
100               
101             transform = CGAffineTransformScale(transform, -1.0, 1.0);    
102               
103             transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);    
104               
105             break;    
106               
107         case UIImageOrientationRight: //EXIF = 8    
108               
109             boundHeight = bounds.size.height;    
110               
111             bounds.size.height = bounds.size.width;    
112               
113             bounds.size.width = boundHeight;    
114               
115             transform = CGAffineTransformMakeTranslation(height, 0.0);    
116               
117             transform = CGAffineTransformRotate(transform, M_PI / 2.0);    
118               
119             break;  
120                          
121         case UIImageOrientationRightMirrored:   
122               
123             boundHeight = bounds.size.height;    
124               
125             bounds.size.height = bounds.size.width;    
126               
127             bounds.size.width = boundHeight;    
128               
129             transform = CGAffineTransformMakeScale(-1.0, 1.0);    
130               
131             transform = CGAffineTransformRotate(transform, M_PI / 2.0);    
132               
133             break;    
134                                                                      
135         default:    
136               
137             [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];    
138               
139     }    
140        
141     UIGraphicsBeginImageContext(bounds.size);    
142              
143     CGContextRef context = UIGraphicsGetCurrentContext();    
144             
145     if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {    
146           
147         CGContextScaleCTM(context, -scaleRatio, scaleRatio);    
148           
149         CGContextTranslateCTM(context, -height, 0);    
150           
151     }    
152       
153     else {    
154           
155         CGContextScaleCTM(context, scaleRatio, -scaleRatio);    
156           
157         CGContextTranslateCTM(context, 0, -height);    
158           
159     }    
160          
161     CGContextConcatCTM(context, transform);    
162          
163     CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);    
164       
165     UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();  
166          
167     UIGraphicsEndImageContext();    
168          
169     return imageCopy;    
170       
171 } 
View Code

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

posted @ 2016-01-18 16:22  晒太阳的仙人掌  阅读(625)  评论(0编辑  收藏  举报