iOS UIImage 图片裁剪 , 旋转裁剪 , 缩放裁剪 , 平移

汪弘毅
2023-12-01

这里是本人项目的里用的全部代码,可以直接拷贝使用:

CameraCutView.h

```

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface CameraCutView : UIView

@property (nonatomic)  UIImage * mTargetImage;
@property (nonatomic)  UIImage * mResultImage;
@property (nonatomic, assign) CGSize originalImageViewSize;

- (void) showCoverViewWithTargetImg;
//frame 相对于当前屏幕坐标 当前屏幕当中的裁剪范围
-(UIImage *) cutImageWithSpecificRect:(CGRect)frame;
- (UIImage *)selectImage;

// 旋转
- (void)rotationImage:(CGFloat)rotation ;

// 缩放大小
- (void)setZoomWithValue:(CGFloat)zoom;
@end

NS_ASSUME_NONNULL_END

 ```

CameraCutView.m

NS_ASSUME_NONNULL_END

#import "CameraCutView.h"
#import "UIImage+Util.h"

@interface CameraCutView ()

@end

@implementation CameraCutView{
    UIImageView  *_mCameraBgView;
}

- (instancetype)init{
    if (self = [super init]) {
        [self initUI];
        return self;
    }
    return nil;
}

- (void)initUI{
    self.backgroundColor = [UIColor clearColor];
}

- (void)showCoverViewWithTargetImg {

    [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    
    _mCameraBgView.backgroundColor = kColorHex(kColorWhite);
    float scaleValue = [self getScaleNum:_mTargetImage];
    _mTargetImage = [self scaleImage:_mTargetImage toScale:scaleValue];
    if (_mTargetImage != nil) {
        _mCameraBgView = [[UIImageView alloc] init];
    }
    
    float _imageScale = self.frame.size.width / _mTargetImage.size.width;
    _mCameraBgView.frame = CGRectMake(0, 0, _mTargetImage.size.width * _imageScale, _mTargetImage.size.height * _imageScale);
    _originalImageViewSize = CGSizeMake(_mTargetImage.size.width * _imageScale, _mTargetImage.size.height * _imageScale);
    
    _mCameraBgView.image = self.mTargetImage;
 
    [self addSubview:_mCameraBgView];
    
    [self setUserGesture];
}

- (void)setUserGesture {
    [_mCameraBgView setUserInteractionEnabled:YES];
    //添加移动手势
    UIPanGestureRecognizer *moveGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveImage:)];
    [moveGes setMinimumNumberOfTouches:1];
    [moveGes setMaximumNumberOfTouches:1];
    [_mCameraBgView addGestureRecognizer:moveGes];
    
    //添加缩放手势
    UIPinchGestureRecognizer *scaleGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scaleImage:)];
    [_mCameraBgView addGestureRecognizer:scaleGes];
    //添加旋转手势
    UIRotationGestureRecognizer *rotateGes = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateImage:)];
    [_mCameraBgView addGestureRecognizer:rotateGes];
}

// 上下移动
float _lastTransX = 0.0, _lastTransY = 0.0;
- (void)moveImage:(UIPanGestureRecognizer *)sender {
    CGPoint translatedPoint = [sender translationInView:self];
    
    if([sender state] == UIGestureRecognizerStateBegan) {
        _lastTransX = 0.0;
        _lastTransY = 0.0;
    }
    
    CGAffineTransform trans = CGAffineTransformMakeTranslation(translatedPoint.x - _lastTransX, translatedPoint.y - _lastTransY);
    CGAffineTransform newTransform = CGAffineTransformConcat(_mCameraBgView.transform, trans);
    _lastTransX = translatedPoint.x;
    _lastTransY = translatedPoint.y;
    
    if ([self isCanMove:newTransform]) {
        _mCameraBgView.transform = newTransform;
    }
}

// 旋转按钮事件
- (void)rotationImage:(CGFloat)rotation {
    
    CGFloat newRotation =  rotation;
    NSLog(@"newRotation == %f", newRotation);
    CGAffineTransform currentTransform = _mCameraBgView.transform;
    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, newRotation);
    [_mCameraBgView setTransform:newTransform];
    _lastRotation = rotation;
}

// 放大、缩小按钮
- (void)setZoomWithValue:(CGFloat)zoom {
    [self zoomImageWithScale:zoom];
}

// 缩放手势
float _lastScale = 1.0;
- (void)scaleImage:(UIPinchGestureRecognizer *)sender {
    if([sender state] == UIGestureRecognizerStateBegan) {
        _lastScale = 1.0;
        return;
    }
    CGFloat scale = [sender scale]/_lastScale;
    [self zoomImageWithScale:scale];
    _lastScale = [sender scale];
}

- (void)zoomImageWithScale:(CGFloat)scale {
    // scale 小于1为缩小
    if (scale < 1) {
        if (_mCameraBgView.size.width < kScreenWidth) {
            return;
        }
    }
    // scale 大于1为放大
    if (scale > 1) {
        if (_mCameraBgView.size.width > kScreenWidth * 3.5) {
            return;
        }
    }
    
    CGAffineTransform currentTransform = _mCameraBgView.transform;
    CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
    [_mCameraBgView setTransform:newTransform];
}

// 旋转手势
float _lastRotation = 0.0;
- (void)rotateImage:(UIRotationGestureRecognizer *)sender {
    if ([sender state] == UIGestureRecognizerStateEnded) {
        _lastRotation = 0.0;
        return;
    }
    CGFloat rotation = -_lastRotation + [sender rotation];
    
    CGAffineTransform currentTransform = _mCameraBgView.transform;
    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform, rotation);
    [_mCameraBgView setTransform:newTransform];
    _lastRotation = [sender rotation];
}

/***
 方法名称:cutImageWithSpecificRect
 方法用途:根据特定的区域对图片进行裁剪
 方法说明:核心裁剪方法CGImageCreateWithImageInRect(CGImageRef image,CGRect rect)
 ***/
- (UIImage *)cutImageWithSpecificRect:(CGRect)frame {
    float zoomScale = [[_mCameraBgView.layer valueForKeyPath:@"transform.scale.x"] floatValue];
    float rotate = [[_mCameraBgView.layer valueForKeyPath:@"transform.rotation.z"] floatValue];
    float _imageScale = _mTargetImage.size.width/_originalImageViewSize.width;
    //裁剪区域的Size_originalImageViewSize    CGSize    (width = 0, height = 0)
    CGSize cropSize = CGSizeMake(frame.size.width/zoomScale, frame.size.height/zoomScale);
    //裁剪区域的Origin
    CGPoint cropperViewOrigin = CGPointMake((0.0 - _mCameraBgView.frame.origin.x + frame.origin.x)/zoomScale,
                                            (0.0 - _mCameraBgView.frame.origin.y + frame.origin.y)/zoomScale);
    
    if((NSInteger)cropSize.width % 2 == 1)
    {
        cropSize.width = ceil(cropSize.width);
    }
    if((NSInteger)cropSize.height % 2 == 1)
    {
        cropSize.height = ceil(cropSize.height);
    }
    
    CGRect CropRectinImage = CGRectMake((NSInteger)(cropperViewOrigin.x*_imageScale) ,(NSInteger)( cropperViewOrigin.y*_imageScale), (NSInteger)(cropSize.width*_imageScale),(NSInteger)(cropSize.height*_imageScale));
    
    UIImage *rotInputImage = [_mTargetImage imageRotatedByRadians:rotate];
    CGImageRef tmp = CGImageCreateWithImageInRect([rotInputImage CGImage], CropRectinImage);
    self.mResultImage = [UIImage imageWithCGImage:tmp scale:_mTargetImage.scale orientation:_mTargetImage.imageOrientation];
    
    CGImageRelease(tmp);
    return self.mResultImage;
}

- (UIImage *)selectImage {
    
    //self.image是拍照所得的照片
    UIImage *image1 = _mTargetImage;
    
    CGImageRef cgRef = image1.CGImage;
    
    //实际照片大小与屏幕大小之比
    CGFloat widthScale = image1.size.width / kScreenWidth;
    CGFloat heightScale = image1.size.height / kScreenHeight;
    
    //我们所拍照片其实是横屏的
    //多减掉50是因为最后的效果图片的高度有偏差,不知道原因
    CGFloat orignWidth = 226-50;//226
    CGFloat orginHeight = 360;//360

    CGFloat x = (kScreenHeight - orginHeight) * 0.5 * heightScale;
    CGFloat y = (kScreenWidth - orignWidth) * 0.5 * widthScale;
    CGFloat width = orginHeight * heightScale;
    CGFloat height = orignWidth * widthScale;
    
    CGRect r = CGRectMake(x, y, width, height);
    
    CGImageRef imageRef = CGImageCreateWithImageInRect(cgRef, r);
    
    UIImage *thumbScale = [UIImage imageWithCGImage:imageRef];
    //
    image1 = thumbScale;
    
 
    return image1;
}

- (BOOL)isCanMove:(CGAffineTransform )newTransform {
    if (_mCameraBgView.frame.size.height/2  - fabs(newTransform.ty)<=0 ||
        _mCameraBgView.frame.size.width/2 - fabs(newTransform.tx)  <=0) {
        return NO;
    } else {
        return YES;
    }
}

/***
 方法名称:scaleImage:toScale:
 方法用途:图片的伸缩处理
 方法说明:scaleSize:放大或缩小的倍数
 ***/
- (UIImage *)scaleImage:(UIImage *)image toScale:(float)scaleSize {
    UIGraphicsBeginImageContext(CGSizeMake(image.size.width * scaleSize, image.size.height * scaleSize));
    
    [image drawInRect:CGRectMake(0, 0, image.size.width * scaleSize, image.size.height * scaleSize)];
    
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return scaledImage;
}
/***
 方法名称:getScaleNum:
 方法用途:根据图片的宽度为基准,来获取图片伸缩放大的倍数
 方法说明:
 ***/
- (float)getScaleNum:(UIImage *)targetImg {
    CGRect r = [UIScreen mainScreen].bounds;
    float preWidth = targetImg.size.width;
    float scaleValue = 1;
//    scaleValue = r.size.width/preWidth;
    return scaleValue;
}

//图片复原
- (void)reset {
    _mCameraBgView.transform = CGAffineTransformIdentity;
}

@end

UIImage+Util.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (Util)

//设置的外围不变形内部平铺拉伸
- (UIImage*)resizeImageWithTop:(CGFloat)top andLeft:(CGFloat)left andBottom:(CGFloat)bottom andRight:(CGFloat)right;
- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;

@end

NS_ASSUME_NONNULL_END

UIImage+Util.m

#import "UIImage+Util.h"

CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/M_PI;};

@implementation UIImage (Util)

//设置的外围不变形内部平铺拉伸
- (UIImage*)resizeImageWithTop:(CGFloat)top andLeft:(CGFloat)left andBottom:(CGFloat)bottom andRight:(CGFloat)right{
    UIImage *image = self;
    // 设置端盖的值
    CGFloat _top = image.size.height * top;
    CGFloat _left = image.size.width * left;
    CGFloat _bottom = image.size.height * bottom;
    CGFloat _right = image.size.width * right;
    // 设置端盖的值
    UIEdgeInsets edgeInsets = UIEdgeInsetsMake(_top, _left, _bottom, _right);
    // 设置拉伸的模式
    UIImageResizingMode mode = UIImageResizingModeStretch;
    // 拉伸图片
    UIImage *newImage = [image resizableImageWithCapInsets:edgeInsets resizingMode:mode];
    return newImage;
}

- (UIImage *)imageRotatedByRadians:(CGFloat)radians {
    return [self imageRotatedByDegrees:RadiansToDegrees(radians)];
}

- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees {
    // calculate the size of the rotated view's containing box for our drawing space
    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
    CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
    rotatedViewBox.transform = t;
    CGSize rotatedSize = rotatedViewBox.frame.size;
    
    
    // Create the bitmap context
    UIGraphicsBeginImageContext(rotatedSize);
    CGContextRef bitmap = UIGraphicsGetCurrentContext();
    
    // Move the origin to the middle of the image so we will rotate and scale around the center.
    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
    
    //   // Rotate the image context
    CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
    
    // Now, draw the rotated/scaled image into the context
    CGContextScaleCTM(bitmap, 1.0, -1.0);
    CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
    
}

@end

 

下面是调用代码

@interface BitiPhotoVC ()
@property (nonatomic, strong) CameraCutView *cutView;

@end

 // 图片展示
    self.cutView.mTargetImage = [UIImage imageNamed:<#(nonnull NSString *)#>]
    self.cutView.originalImageViewSize = CGSizeMake(width, height);
    [self.cutView showCoverViewWithTargetImg];

 

 类似资料: