zoukankan      html  css  js  c++  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),用来作为坐标系的标准。所以所有的变化都由前两列完成。

    以上参数在矩阵中的表示为:

     |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);    
    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. }   

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

  • 相关阅读:
    Beware of GPU memory bandwidth
    XNA中的RenderTarget
    Scene Management Culling
    More on Scene Management
    关于quaternion的笔记
    用XNA显示GPU系统信息
    Scene Management Collision Detection
    些关于引擎设计,Scene Management的文章
    XNA下的中文显示
    Skeletal Model and Skinning Animation
  • 原文地址:https://www.cnblogs.com/56ik/p/5135320.html
Copyright © 2011-2022 走看看