IOS图片处理中的问题

IOS图片处理项目遇到的问题


最近项目中碰到图像处理跟动画,记录下来,当你看到是希望对你有所帮助。
所谓难者不会,会者不难,有不对的地方欢迎不吝赐教,大神轻喷。

矩阵

struct CGAffineTransform
{
CGFloat a, b, c, d;
CGFloat tx, ty;
};

矩阵变换后的坐标计算

/**
 *  方法一
 *
 */
//变换前
CGPoint point = CGPointMake(x, y);
CGFloat x1 = ax + cy + tx;  
CGFloat y1 = bx + dy + ty;
//变换后
CGPoint point = CGPointMake(x1, y1);

/**
 *  方法二
 *
 *  @param rect 要转化的rect
 *  @param transform 变换后的transform
 */
CGRect rect;
CGAffineTransform transform;
CGRectApplyAffineTransform(rect, transform);

/*==============================================*/
//转换点的方法
CGPointApplyAffineTransform(<#CGPoint point#>, <#CGAffineTransform t#>)

视图绕某一点旋转


// 调用方法
[self correctAnchorPointForView:view];
CGAffineTransform transform = CGAffineTransformRotate(_lastTransform, (M_PI*count/2));    self.fatherView.transform = transform;
[self setDefaultAnchorPointforView:view];

#pragma mark -- private methods 图片中心点操作
- (void)setDefaultAnchorPointforView:(UIView *)view
{
    [self setAnchorPoint:CGPointMake(0.5f, 0.5f) forView:view];
}
- (void)correctAnchorPointForView:(UIView *)view
{
    CGPoint anchorPoint = CGPointZero;
    CGPoint superviewCenter = view.superview.center;
    //   superviewCenter是view的superview 的 center 在view.superview.superview中的坐标。
    CGPoint viewPoint = [view convertPoint:superviewCenter fromView:view.superview.superview];
    //   转换坐标,得到superviewCenter 在 view中的坐标
    anchorPoint.x = (viewPoint.x) / view.bounds.size.width;
    anchorPoint.y = (viewPoint.y) / view.bounds.size.height;
    [self setAnchorPoint:anchorPoint forView:view];
}
- (void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
    CGPoint oldOrigin = view.frame.origin;
    view.layer.anchorPoint = anchorPoint;
    CGPoint newOrigin = view.frame.origin;
    CGPoint transition;
    transition.x = newOrigin.x - oldOrigin.x;
    transition.y = newOrigin.y - oldOrigin.y;
    view.center = CGPointMake (view.center.x - transition.x, view.center.y - transition.y);
}

⚠️⚠️⚠️注意
通过矩阵变换来操作视图会改变视图的坐标系。给视图添加移动手势的时候可能会出现错乱的现象
要把视图的坐标系转换以后再进行操作

图片处理

截图方法:
截图的时候发现图片截的有问题 注意这里的rect是图片的分辨率

CGRect rect = CGRectMake((CGImageGetWidth(cgImage))*37*PB_ScreenRatio/theImage.size.width, CGImageGetHeight(cgImage)*(31+PB_NaviHeight)/theImage.size.height, CGImageGetWidth(cgImage)*kWidth/PB_ScreenW, CGImageGetHeight(cgImage)*KHeight/PB_ScreenH);
    CGImageRef imageRefRect = CGImageCreateWithImageInRect(cgImage, rect);
    UIImage * newImage = [UIImage imageWithCGImage:imageRefRect];
    UIGraphicsEndImageContext();

图片旋转 获取旋转后的image

+ (UIImage *)ehs_imageWithRotation:(UIImage *)image rotationDegree:(CGFloat)degree
{
    //将image转化成context
    //获取图片像素的宽和高
    size_t width =  image.size.width * image.scale;
    size_t height = image.size.height * image.scale;
    
    //颜色通道为8 因为0-255 经过了8个颜色通道的变化
    //每一行图片的字节数 因为我们采用的是ARGB/RGBA 所以字节数为 width * 4
    size_t bytesPerRow =width * 4;
    //图片的透明度通道
    CGImageAlphaInfo info =kCGImageAlphaPremultipliedFirst;
    CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, bytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault|info);
    
    if (!context) {
        return nil;
    }
    //将图片渲染到图形上下文中
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage);
    
    //旋转context
    uint8_t* data =(uint8_t*) CGBitmapContextGetData(context);
    //旋转欠的数据
    vImage_Buffer src = { data,height,width,bytesPerRow};
    //旋转后的数据
    vImage_Buffer dest= { data,height,width,bytesPerRow};
    
    //背景颜色
    Pixel_8888  backColor = {0,0,0,0};
    //填充颜色
    vImage_Flags flags = kvImageBackgroundColorFill;
    
    vImageRotate_ARGB8888(&src, &dest, nil, degree * M_PI/180.f, backColor, flags);
    
    //将conetxt转换成image
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage  * rotateImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    
    return  rotateImage;
}

获取镜像后的图片

+ (UIImage *)fixOrientation:(UIImage *)aImage rotation:(UIImageOrientation)orientation{
    if (orientation == UIImageOrientationUp)
        
        return aImage;
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (orientation) {
            
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (orientation) {
            
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }
    
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

绘制

项目中碰到一个这样的需求 要给图片覆膜效果如下

//这里不能直接添加一个view,要改变image的overlay
[image drawInRect:CGRectMake(0, 0, rect.size.width, currentWavePointY) blendMode:kCGBlendModeOverlay alpha:1.0];

绘制半透明贝塞尔曲线


UIImage *image = [PB_ImageColor imageWithColor:PB_UIColor(0x80FFFFFF) size:rect.size];
            [image drawInRect:CGRectMake(0, currentWavePointY, rect.size.width, rect.size.height-currentWavePointY) blendMode:kCGBlendModeNormal alpha:1.0];
            UIBezierPath *path = [[UIBezierPath alloc]init];
            [path moveToPoint:startPoint];
            [path addCurveToPoint:endPoint controlPoint1:controlPoint1 controlPoint2:controlPoint2];
            // 创建 shapeLayer
            _firstWaveLayer = [[CAShapeLayer alloc]init];
            [self.layer addSublayer:_firstWaveLayer];
            _firstWaveLayer.path = path.CGPath;
            _firstWaveLayer.fillColor = [UIColor clearColor].CGColor;
            _firstWaveLayer.strokeColor = _firstWaveColor.CGColor;
            _firstWaveLayer.lineWidth = 8;
            
            UIBezierPath *path1 = [[UIBezierPath alloc]init];
            [path1 moveToPoint:startPointA];
            [path1 addCurveToPoint:endPointA controlPoint1:controlPoint1A controlPoint2:controlPoint2A];
            // 创建 shapeLayer
            _secondWaveLayer = [[CAShapeLayer alloc]init];
            [self.layer addSublayer:_secondWaveLayer];
            _secondWaveLayer.path = path1.CGPath;
            _secondWaveLayer.fillColor = [UIColor clearColor].CGColor;
            _secondWaveLayer.strokeColor = PB_UIColorAlphaHalf(0xE1E1E1).CGColor;
            _secondWaveLayer.lineWidth = 8;

//半透明效果
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size{
    if (!color || size.width <= 0 || size.height <= 0) return nil;
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

滤镜

滤镜使用GPUImage
参考[https://www.jianshu.com/p/c5c5f806473c]

图片缩放

这里碰到了旋转后的图片缩放

方法比较麻烦,没想到好的办法硬着头皮算,上图比较好理解
在这里插入图片描述

 原理:前提1.view的大小跟image相同 旋转完以后view大小变成红色部分
                   2.假设边框大小跟image大小相同 即为绿色部分
      保持view内image大小不变 计算新的view的frame ,根据新的frame计算缩放比例
      重新赋值给frame, 要使黄色区域超出边框 要计算出边框点到黄色区域的距离,取最大距离来进行等比例缩放。
      以下是涉及到的计算公式
      //边框顶点 到图片iamge的距离
      //(y - p1.y)/(p2.y-p1.y) = (x - p1.x)/(p2.x - p1.x)
      //海伦公式 s = sqrt(p(p-a)(p-b)(p-c));
      //两点之间的距离 ABS(AB) = sqrt((x1-x2)(x1-x2)+(y1 - y2)(y1 - y2))

代码有点乱就不上代码乱。如有不妥欢迎指正。

qq:604630178

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值