[iOS]对UIView和UIImage的部分截屏

接到这样一个需求,要对APP中所有拍照和选择的图片的地方先让用户对图片进行编辑(只是寻常的旋转、剪切),然后再上传。

截取的方式一

一开始因为对UIGraphics的方法不怎么熟悉,以为只能对UIView的整个截屏。于是就弄出了这种截取部分图片的方式,就是用CropView包住ImageView然后截取CropView。虽然效果也还不错也能满足一些需求,但是这样的截图变得不高清,所以最后放弃了用它。

/// 截图 
+ (UIImage *)cropImageWithOldImage:(UIImage *)image OldFrame:(CGRect)oldFrame CropFrame:(CGRect)cropFrame {
    image = [self fixOrientation:image];
    
    float bs = 2;
    UIView *cropView = [[UIView alloc] initWithFrame:CGRectMake(cropFrame.origin.x*bs, cropFrame.origin.y*bs, cropFrame.size.width*bs, cropFrame.size.height*bs)]; // cropFrame
    cropView.backgroundColor = [UIColor clearColor];
    [cropView.layer setMasksToBounds:YES];
    
    UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(-cropFrame.origin.x*bs, -cropFrame.origin.y*bs, oldFrame.size.width*bs, oldFrame.size.height*bs)];
    tempImageView.contentMode = UIViewContentModeScaleAspectFill;
    tempImageView.image = image;
    tempImageView.backgroundColor = [UIColor clearColor];
    [cropView addSubview:tempImageView];
    return [self screenshotsFromView:cropView];
}

/// 从UIView截图
+ (UIImage *)screenshotsFromView:(UIView *)shareView {
    // currentView 当前的view  创建一个基于位图的图形上下文并指定大小为
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(shareView.frame.size.width, shareView.frame.size.height), NO, 0.0);
    // renderInContext呈现接受者及其子范围到指定的上下文
    [shareView.layer renderInContext:UIGraphicsGetCurrentContext()];
    // 返回一个基于当前图形上下文的图片
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    // 移除栈顶的基于当前位图的图形上下文
    UIGraphicsEndImageContext();
    // 保存图片
    //UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
    return viewImage;
}

/// 图片方向调整
+ (UIImage *)fixOrientation:(UIImage *)aImage {
    // No-op if the orientation is already correct
    if (aImage.imageOrientation == UIImageOrientationUp)
        return aImage;
    
    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (aImage.imageOrientation) {
        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 (aImage.imageOrientation) {
        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;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    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;
    }
    
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

截取的方式二

弄清UIGraphics才能解决问题,UIGraphicsBeginImageContextWithOptions(rct.size, NO, image.scale)传递一个绘制的size,然后[image drawAtPoint:origin]再传递绘制的左上角的点,最后得到了需要的图片。

/// 截图 保证清晰度
+ (UIImage *)editImageWithOldImage:(UIImage *)image OldFrame:(CGRect)oldFrame CropFrame:(CGRect)cropFrame Scale:(float)scale {
    image = [self fixOrientation:image];
    CGSize editSize = oldFrame.size;
    CGSize imgSize = image.size;
    CGFloat widthScale;
    CGRect rct;
    if (imgSize.width < editSize.width) {
        widthScale = imgSize.width / editSize.width;
        rct = CGRectMake(cropFrame.origin.x*widthScale, cropFrame.origin.y*widthScale, cropFrame.size.width*widthScale, cropFrame.size.height*widthScale);
    } else {
        widthScale = editSize.width / imgSize.width;
        rct = CGRectMake(cropFrame.origin.x/widthScale, cropFrame.origin.y/widthScale, cropFrame.size.width/widthScale, cropFrame.size.height/widthScale);
    }

    CGPoint origin = CGPointMake(-rct.origin.x, -rct.origin.y);
    UIImage *img = nil;
    UIGraphicsBeginImageContextWithOptions(rct.size, NO, image.scale);
    [image drawAtPoint:origin];
    img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return img;
}

示意图:

拍照后只取框内部分
[iOS]对UIView和UIImage的部分截屏_第1张图片

确认时只取框内部分

[iOS]对UIView和UIImage的部分截屏_第2张图片

处理后就这样

[iOS]对UIView和UIImage的部分截屏_第3张图片

你可能感兴趣的:([iOS]学习笔记)