• 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;  
                             
            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;    
          
    }   
    
    
  • 相关阅读:
    linux 下 设置 MySQL8 表名大小写不敏感方法,解决设置后无法启动 MySQL 服务的问题
    JavaWeb入门_模仿天猫整站Tmall_JavaEE实践项目
    flowable工作流笔记
    bladex前端反向代理(解决跨域)
    Long类型传值前端精度丢失
    blade普通字典关联
    一些东西
    java面试题经典解读
    html元素定位原理
    行转换为列
  • 原文地址:https://www.cnblogs.com/tig666666/p/7345883.html
Copyright © 2020-2023  润新知