[iOS]自定义相机进行拍照购

demo:https://download.csdn.net/download/u012881779/10744408
之前做电商平台的图片搜索时使用自定义相机和图片剪切写的一个demo,类似于京东和淘宝的图片搜索功能。
示意图:

自定义相机:

 

#import <UIKit/UIKit.h>
#import "ResultViewController.h"

typedef void(^customSelectImageViewBlock)(UIImage *selectImage);

@interface GACustomCameraViewController : UIViewController

@property (nonatomic, strong) customSelectImageViewBlock selectImage;

@end
#import "GACustomCameraViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>

@interface GACustomCameraViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property (weak, nonatomic) IBOutlet UIButton *theFlashBut;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *statusHighConstraint;
@property (strong, nonatomic) AVCaptureSession *session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer;
@property (strong, nonatomic) AVCaptureDevice *device;
@property (strong, nonatomic) AVCaptureDeviceInput *deviceInput;
@property (strong, nonatomic) AVCaptureStillImageOutput *imageOutput;
@property (strong, nonatomic) AVCaptureConnection *connection;

@end

@implementation GACustomCameraViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 判断相机 是否可以使用
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        NSLog(@"sorry, no camera or camera is unavailable.");
        return;
    }
    // 设置相机
    [self initCameraSettings];
    // 当前闪光灯状态
    if (self.device.flashMode == AVCaptureFlashModeOff) {
        _theFlashBut.selected = NO;
    } else {
        _theFlashBut.selected = YES;
    }
    // 状态栏高度
    _statusHighConstraint.constant = [[UIApplication sharedApplication] statusBarFrame].size.height;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:YES];
    if (self.session) {
        [self.session startRunning];
    }
    [self shatusViewHidden:NO];
    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:YES];
    if (self.session) {
        [self.session stopRunning];
    }
    // [self shatusViewHidden:NO];
    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
}

// 状态栏显示/隐藏
- (void)shatusViewHidden:(BOOL)result {
    UIView *statusView = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
    statusView.hidden = result;
}

// 初始化相机
- (void)initCameraSettings {
    NSError *error;
    // 创建会话层
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    // 初始化session
    self.session = [[AVCaptureSession alloc] init];
    if ([self.session canSetSessionPreset:AVCaptureSessionPresetPhoto]) {
        self.session.sessionPreset = AVCaptureSessionPresetPhoto;
    }
    // 初始化输入设备
    self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
    // 初始化照片输出对象
    self.imageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
    [self.imageOutput setOutputSettings:outputSettings];
    // 判断输入输出设备是否可用
    if ([self.session canAddInput:self.deviceInput]) {
        [self.session addInput:self.deviceInput];
    }
    if ([self.session canAddOutput:self.imageOutput]) {
        [self.session addOutput:self.imageOutput];
    }
    // 初始化预览图层
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    /** 设置图层的填充样式
     AVLayerVideoGravityResize, // 非均匀模式。两个维度完全填充至整个视图区域
     AVLayerVideoGravityResizeAspect, // 等比例填充,直到一个维度到达区域边界
     AVLayerVideoGravityResizeAspectFill, // 等比例填充,直到填充满整个视图区域,其中一个维度的部分区域会被裁剪
     */
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.previewLayer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
    [self.view.layer insertSublayer:self.previewLayer atIndex:0];
}

// 返回
- (IBAction)returnAction:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)returnWithImage:(UIImage *)image {
    /*
    // 在首页跳转
    [self returnAction:nil];
    if (self.selectImage) {
        self.selectImage(image);
    }*/
    // 在自定义相机跳转
    [self entryRsultVCWithImage:image];
}

- (void)entryRsultVCWithImage:(UIImage *)image {
    ResultViewController *result = [[ResultViewController alloc] initWithNibName:@"ResultViewController" bundle:nil];
    result.originalImage = image;
    [self presentViewController:result animated:YES completion:nil];
}

// 闪光灯
- (IBAction)theFlashAction:(id)sender {
    AVCaptureFlashMode mode;
    UIButton *tempBut = (UIButton *)sender;
    if (tempBut.isSelected) {
        tempBut.selected = NO;
        mode = AVCaptureFlashModeOff;
    } else {
        tempBut.selected = YES;
        mode = AVCaptureFlashModeOn;
    }
    if ([self.device isFlashModeSupported:mode]) {
        [self.session beginConfiguration];
        [self.device lockForConfiguration:nil];
        [self.device setFlashMode:mode]; // 这行代码就要放在这个顺序的位置否则会崩溃
        [self.device unlockForConfiguration];
        [self.session commitConfiguration];
        [self.session startRunning];
    }
}

// 拍照
- (IBAction)takePhotoAction:(id)sender {
    self.connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
    [self.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
    [self.imageOutput captureStillImageAsynchronouslyFromConnection:self.connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [UIImage imageWithData:jpegData];
        [self returnWithImage:image];
    }];
}

// 前置/后置摄像头
- (IBAction)frontOrRearCameraAction:(id)sender {
    [UIView beginAnimations:@"animation" context:nil];
    [UIView setAnimationDuration:.5f];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
    [UIView commitAnimations];
    
    NSArray *inputs = self.session.inputs;
    for ( AVCaptureDeviceInput *input in inputs ) {
        AVCaptureDevice *device = input.device;
        if ( [device hasMediaType:AVMediaTypeVideo] ) {
            AVCaptureDevicePosition position = device.position;
            AVCaptureDevice *newCamera = nil;
            AVCaptureDeviceInput *newInput = nil;
            if (position == AVCaptureDevicePositionFront) {
                newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
            } else {
                newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
            }
            newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
            [self.session beginConfiguration];
            [self.session removeInput:input];
            [self.session addInput:newInput];
            [self.session commitConfiguration];
            break;
        }
    }
}

// 相机状态
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for ( AVCaptureDevice *device in devices ) {
        if ( device.position == position ) {
            return device;
        }
    }
    return nil;
}

// 打开相册
- (IBAction)openAlbumAction:(id)sender {
    UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
    pickerController.delegate = self;
    pickerController.navigationBar.translucent = NO;
    pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    pickerController.edgesForExtendedLayout = UIRectEdgeNone;
    [self presentViewController:pickerController animated:YES completion:nil];
}

#pragma mark - 从相册选择图片后操作

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 获取拍照的图像
    // UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    // 获取图片裁剪的图
    // UIImage *edit = [info objectForKey:UIImagePickerControllerEditedImage];
    // 获取照片的原图
    UIImage *original = [info objectForKey:UIImagePickerControllerOriginalImage];
    [picker dismissViewControllerAnimated:NO completion:^{
        [self returnWithImage:original];
    }];
}

#pragma mark - 取消操作时调用

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:nil];
}

@end

结果展示页:

 

#import <UIKit/UIKit.h>

@interface ResultViewController : UIViewController

@property (strong, nonatomic) UIImage *originalImage;

@end
#import "ResultViewController.h"
#import "YBPictureCutterView.h"

static float const LIMIT_SV_BOTTOM = 120.0;     // scrollView底部最大移动范围
static float const LIMIT_DRAG_DISTANCE = 44.0;  // 拖动超过响应范围后自动滚动到约束位置
static float const LIMIT_CO_TOP = 100.0;        // 约束内容视图顶部
static float const LIMIT_CO_BOTTOM = 200.0;     // 约束图片视图底部

@interface ResultViewController () <YBPictureCutterViewDataSource, YBPictureCutterViewDelegate, UIGestureRecognizerDelegate>

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
@property (weak, nonatomic) IBOutlet UIView *contentTitleBGView;
@property (weak, nonatomic) IBOutlet UIImageView *tempShowIV;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *ivBottomConstraint;    // 图片区域的bottom约束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentTopConstraint;  // 内容区域的top约束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *scrollViewBottomConstraint; // 图片区域sv的bottom约束
@property (strong, nonatomic) YBPictureCutterView *cutterView;
@property (strong, nonatomic) UIImageView *showImageView;
@property (assign, nonatomic) CGPoint startPoint;   // 开始拖动时的起始点
@property (assign, nonatomic) CGFloat startTopY;    // 开始拖动时的内容区域top约束
@property (assign, nonatomic) CGFloat startSCBottomY;   // 开始拖动时图片区域Bottom约束
@property (assign, nonatomic) CGFloat startSCOffSetY;   // 开始拖动时图片区域offset.y

@end

@implementation ResultViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _contentTopConstraint.constant = LIMIT_CO_TOP;
    _ivBottomConstraint.constant = LIMIT_CO_BOTTOM;
    _scrollViewBottomConstraint.constant = LIMIT_SV_BOTTOM;
    // UIView部分倒圆角
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:_contentTitleBGView.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = _contentTitleBGView.bounds;
    maskLayer.path = maskPath.CGPath;
    _contentTitleBGView.layer.mask = maskLayer;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self updateScrollViewWithDev:0];
    [_scrollView addSubview:self.showImageView];
    self.showImageView.image = _originalImage;
    [self.showImageView addSubview:self.cutterView];
    self.showImageView.userInteractionEnabled = YES;
    [self adaptationSafeAreaWith:_scrollView useArea:1];
}

- (void)updateScrollViewWithDev:(float)dev {
    float hbw = _originalImage.size.height/(float)_originalImage.size.width;
    float newWidth = [UIScreen mainScreen].bounds.size.width;
    float newHeight = newWidth*hbw;
    float devY = 0;
    BOOL result = NO;
    if (_scrollView.frame.size.height > newHeight) {
        devY = (_scrollView.frame.size.height - newHeight)/2.0;
    } else {
        result = YES;
    }
    [_scrollView setContentSize:CGSizeMake(newWidth, newHeight)];
    self.showImageView.frame = CGRectMake(0, devY, newWidth, newHeight);
    if (result) {
        CGPoint oldOffset = _scrollView.contentOffset;
        oldOffset.y = _startSCOffSetY - dev;
        CGFloat jgHeight = _scrollView.contentSize.height-_scrollView.frame.size.height;
        if (oldOffset.y < 0) {
            oldOffset.y = 0;
        } else if (oldOffset.y > jgHeight) {
            oldOffset.y = jgHeight;
        }
        [_scrollView setContentOffset:oldOffset];
    }
}

- (UIImageView *)showImageView {
    if (!_showImageView) {
        _showImageView = [UIImageView new];
        [_showImageView setContentMode:UIViewContentModeScaleToFill];
    }
    return _showImageView;
}

- (YBPictureCutterView *)cutterView {
    if (!_cutterView) {
        _cutterView = [[YBPictureCutterView alloc] init];
        _cutterView.dataSource = self;
        _cutterView.delegate = self;
    }
    _cutterView.frame = _showImageView.bounds;
    return _cutterView;
}

#pragma mark - pictureCutterView dataSource & delegate

- (UIImage *)imageForPictureCutterView:(YBPictureCutterView *)cutterView {
    return _showImageView.image;
}

- (void)pictureCutterView:(YBPictureCutterView *)cutterView didClippedImage:(UIImage *)image {
    NSLog(@"%@", NSStringFromCGSize(image.size));
    _tempShowIV.image = image;
}


- (IBAction)returnAction:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

/**
 * 适配iPhone X的安全区域
 * isUse = 1 表示使用安全区域
 * isUse = 0 表示不使用安全区域
 */
- (void)adaptationSafeAreaWith:(UIScrollView *)sv useArea:(NSInteger)isUse {
#ifdef __IPHONE_11_0
    if ([sv respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
        if (isUse) {
            if (@available(iOS 11.0, *)) {
                sv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
                if ([[sv class] isSubclassOfClass:[UITableView class]]) {
                    UITableView *tv = (UITableView *)sv;
                    [tv setInsetsContentViewsToSafeArea:NO];
                }
            } else {
                // Fallback on earlier versions
            }
        } else {
            if (@available(iOS 11.0, *)) {
                sv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways;
            } else {
                // Fallback on earlier versions
            }
        }
    }
#endif
}

#pragma mark - PanGestureRecognizer手势

- (IBAction)contentViewPanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
    UIView *tempView = gestureRecognizer.view;
    if (tempView.tag == 567) {
        CGPoint tempPoint = [gestureRecognizer locationInView:self.view];
        // 图片ScrollView底部约束移动范围
        CGFloat scMaxMoveRange = LIMIT_SV_BOTTOM;
        // 图片ScrollView移动范围/内容View移动范围
        CGFloat bl = scMaxMoveRange/(float)([UIScreen mainScreen].bounds.size.height - LIMIT_CO_TOP - LIMIT_CO_BOTTOM);
        CGFloat scrHeight = [UIScreen mainScreen].bounds.size.height;
        CGFloat devY = tempPoint.y-_startPoint.y;
        CGFloat newY = _startTopY + devY;
        if (newY >= LIMIT_CO_TOP) {
            if (newY <= (scrHeight - LIMIT_CO_BOTTOM)) {
                _contentTopConstraint.constant = newY;
                _scrollViewBottomConstraint.constant = _startSCBottomY - bl*devY;
                [self updateScrollViewWithDev:bl*devY];
            } else {
                [self toBottomLocationWithConstant:0 Dev:0];
                return;
            }
        } else {
            [self toTopLocationWithConstant:scMaxMoveRange Dev:0];
            return;
        }
        // 判断是否拖动结束
        if (gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
            CGFloat responseRange = LIMIT_DRAG_DISTANCE;
            BOOL result = NO;
            if (devY > 0) {
                if (devY >= responseRange) {
                    [self toBottomLocationWithConstant:0 Dev:bl*devY];
                } else {
                    result = YES;
                }
            } else if (devY < 0) {
                if (devY <= (0 - responseRange)) {
                    [self toTopLocationWithConstant:scMaxMoveRange Dev:bl*devY];
                } else {
                    result = YES;
                }
            }
            if (result) {
                [self toOldLocationWithConstant:self.startSCBottomY Dev:bl*devY];
            }
        }
    }
}

// 滚动到底部位置
- (void)toBottomLocationWithConstant:(float)constant Dev:(float)dev {
    self.scrollViewBottomConstraint.constant = constant;
    [self.view layoutIfNeeded];
    [UIView animateWithDuration:0.3 animations:^{
        self.contentTopConstraint.constant = [UIScreen mainScreen].bounds.size.height - LIMIT_CO_BOTTOM;
        [self updateScrollViewWithDev:dev];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        self.collectionView.scrollEnabled = NO;
    }];
}

// 滚动到顶部位置
- (void)toTopLocationWithConstant:(float)constant Dev:(float)dev {
    self.scrollViewBottomConstraint.constant = constant;
    [self.view layoutIfNeeded];
    [UIView animateWithDuration:0.3 animations:^{
        self.contentTopConstraint.constant = LIMIT_CO_TOP;
        [self updateScrollViewWithDev:dev];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        self.collectionView.scrollEnabled = YES;
    }];
}

// 滚动回到原位置
- (void)toOldLocationWithConstant:(float)constant Dev:(float)dev {
    self.scrollViewBottomConstraint.constant = constant;
    [self.view layoutIfNeeded];
    [UIView animateWithDuration:0.3 animations:^{
        self.contentTopConstraint.constant = self.startTopY;
        [self updateScrollViewWithDev:dev];
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
        if (self.startTopY == LIMIT_CO_TOP) {
            self.collectionView.scrollEnabled = YES;
        }
    }];
}

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    UIView *tempView = gestureRecognizer.view;
    if (tempView.tag == 567) {
        _startPoint = [gestureRecognizer locationInView:self.view];
        _startSCBottomY = _scrollViewBottomConstraint.constant;
        _startSCOffSetY = _scrollView.contentOffset.y;
        _startTopY = _contentTopConstraint.constant;
        CGFloat tempLimitBottom = [UIScreen mainScreen].bounds.size.height - LIMIT_CO_BOTTOM;
        if (_startTopY != LIMIT_CO_TOP && _startTopY != tempLimitBottom) {
            if (_startTopY-LIMIT_CO_TOP < tempLimitBottom-_startTopY) {
                _startTopY = LIMIT_CO_TOP;
            } else {
                _startTopY = tempLimitBottom;
            }
        }
    }
    return YES;
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.tag == 2000) {
        CGPoint offset = scrollView.contentOffset;
        if (offset.y <= 0) {
            offset.y = 0;
            scrollView.contentOffset = offset;
            self.collectionView.scrollEnabled = NO;
        } else {

        }
    }
}

@end

图片剪切:
YBPictureCutterView

#import <UIKit/UIKit.h>

@class YBPictureCutterView;
@protocol YBPictureCutterViewDataSource <NSObject>

@required
// 提供被处理的图片
- (UIImage *)imageForPictureCutterView:(YBPictureCutterView *)cutterView;

@end

@protocol YBPictureCutterViewDelegate <NSObject>

@optional
// 返回被裁剪过的图片
- (void)pictureCutterView:(YBPictureCutterView *)cutterView didClippedImage:(UIImage *)image;

@end

@interface YBPictureCutterView : UIView

@property (nonatomic, weak) id<YBPictureCutterViewDataSource> dataSource;
@property (nonatomic, weak) id<YBPictureCutterViewDelegate> delegate;

- (void)dismiss;

@end
#import "YBPictureCutterView.h"
#import "YBPhotoCutView.h"
#import "UIImage+FixOrientation.h"

@interface YBPictureCutterView () <YBPhotoCutViewDelegate>

@property (nonatomic, strong) YBPhotoCutView *cutView;
@property (nonatomic, strong) UIImageView *imgView;
@property (nonatomic, assign) CGRect cutFrame;
@property (nonatomic, strong) UIImage *image;

@end

@implementation YBPictureCutterView

#pragma mark - life cycle

- (instancetype)init {
    if (self = [super init]) {
        self.backgroundColor = [UIColor blackColor];
    }
    return self;
}

- (void)didMoveToWindow {
    [super didMoveToWindow];
    [self addSubview:self.imgView];
    [self addSubview:self.cutView];
}

#pragma mark - public method

- (void)dismiss {
    [self removeFromSuperview];
}

#pragma mark - YBPhotoCutView delegate

- (void)photoCutView:(YBPhotoCutView *)customView shotFrame:(CGRect)frame {
    self.cutFrame = frame;
    [self delegateInvocation];
}

- (void)delegateInvocation {
    if ([self.delegate respondsToSelector:@selector(pictureCutterView:didClippedImage:)]) {
        UIImage *image = [self cutImage];
        if (image) {
            [self.delegate pictureCutterView:self didClippedImage:image];
        }
    }
}

#pragma mark - 图片剪裁

- (UIImage *)cutImage {
    if (self.cutFrame.size.height == 0) {
        return nil;
    }
    double scale = self.imgView.image.size.width / self.imgView.frame.size.width;
    CGFloat x = self.cutFrame.origin.x *scale;
    CGFloat y = self.cutFrame.origin.y *scale;
    CGFloat w = self.cutFrame.size.width *scale;
    CGFloat h = self.cutFrame.size.height *scale;
    CGRect cropRect = CGRectMake(x, y, w, h);
    // 直接使用图片会发现image的方向不对
    // CGImageRef imageRef = CGImageCreateWithImageInRect([self.imgView.image CGImage], cropRect);
    // 需要处理以下图片的方向问题
    CGImageRef imageRef = CGImageCreateWithImageInRect([[self.imgView.image fixOrientation] CGImage], cropRect);
    UIImage *img = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    self.cutFrame = CGRectZero;
    return img;
}

#pragma mark - lazy load

- (YBPhotoCutView *)cutView {
    self.cutFrame = CGRectMake(self.bounds.size.width/4, self.bounds.size.height/4, self.bounds.size.width/2, self.bounds.size.height/2);
    if (!_cutView) {
        _cutView = [[YBPhotoCutView alloc] initWithFrame:self.bounds pictureFrame:self.cutFrame];
        _cutView.delegate = self;
        [self delegateInvocation];
    }
    return _cutView;
}

- (UIImageView *)imgView {
    if (!_imgView) {
        _imgView = [[UIImageView alloc] init];
        _imgView.frame = self.bounds;
    }
    _imgView.image = self.image;
    return _imgView;
}

- (UIImage *)image {
    return [self.dataSource imageForPictureCutterView:self];
}

@end

YBPhotoCutView

#import <UIKit/UIKit.h>

@class YBPhotoCutView;
@protocol YBPhotoCutViewDelegate <NSObject>

@optional
// 返回裁剪框frame
- (void)photoCutView:(YBPhotoCutView *)customView shotFrame:(CGRect)frame;

@end

@interface YBPhotoCutView : UIControl

@property (nonatomic, assign) id<YBPhotoCutViewDelegate> delegate;
// 剪切框的frame
@property (nonatomic, assign, readonly) CGRect pictureFrame;
@property (nonatomic, assign) CGFloat minWidth;
@property (nonatomic, assign) CGFloat minHeight;

// frame是总视图大小,picFrame是剪切框大小
- (instancetype)initWithFrame:(CGRect)frame pictureFrame:(CGRect)picFrame;

@end


@interface YBMath : NSObject

// 极坐标
typedef struct {
    double radius;  // 半径
    double angle;   // 角度
} YBPolarCoordinate;

// 矩形的四个角坐标
typedef struct {
    CGPoint topLeftPoint;
    CGPoint topRightPoint;
    CGPoint bottomLeftPoint;
    CGPoint bottomRightPoint;
} CornerPoint;

// 矩形的四个边中心点
typedef struct {
    CGPoint top;
    CGPoint bottom;
    CGPoint left;
    CGPoint right;
} DirectionPoint;

// 四个边中心点的矩形
typedef struct {
    CGRect topRect;
    CGRect bottomRect;
    CGRect leftRect;
    CGRect rightRect;
} DirectionRect;

// 直角坐标转极坐标
YBPolarCoordinate decartToPolar(CGPoint center, CGPoint point);
// 根据frame计算矩形四个角的坐标
CornerPoint frameToCornerPoint(CGRect frame);
// 根据矩形四个角计算四条边中心点
DirectionPoint cornerPointToDirection(CornerPoint corner);
// 根据矩形四条边中心点计算中心点的矩形坐标
DirectionRect directionPointToDirectionRect(DirectionPoint drt_point, CGFloat width, CGFloat height);

@end
#import "YBPhotoCutView.h"

// 四个角的触摸范围半径
static CGFloat const touchRadius = 20.0;

// 四个角
typedef NS_ENUM(NSInteger,CornerIndex) {
    TopLeft = 0,
    TopRight,
    BottomLeft,
    BottomRight
};

// 四条边
typedef NS_ENUM(NSUInteger, DirectionIndex) {
    Top = 0,
    Bottom,
    Left,
    Right
};

@implementation YBPhotoCutView {
    // 记录上次的触摸点以计算偏移量
    CGPoint _touchedPoint;
    // YES缩放模式(NO拖动模式,即不改变大小拖动剪切框)
    BOOL _zooming;
    // 拖动缩放的点 0上左:(0,0) 1上右:(1,0) 2下左:(0,1) 3下右:(1,1)
    CornerIndex _zoomingIndex;
    // 拖动缩放的边
    DirectionIndex _zoomingDirection;
    // 截图框四个角的坐标
    CornerPoint _cornerPoint;
    // 四条边中心点
    DirectionPoint _directionPoint;
}

- (instancetype)initWithFrame:(CGRect)frame pictureFrame:(CGRect)picFrame {
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
        self.pictureFrame = picFrame;
        _minHeight = 60.0;
        _minWidth = 60.0;
        _zooming = NO;
        _zoomingDirection = -1;
    }
    return self;
}

- (void)setPictureFrame:(CGRect)pictureFrame {
    _pictureFrame = pictureFrame;
    _cornerPoint = frameToCornerPoint(self.pictureFrame);
    _directionPoint = cornerPointToDirection(_cornerPoint);
}

// 开始触摸跟踪
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchPoint = [touch locationInView:self];
    _touchedPoint = touchPoint;
    // 判断点击的是否是四条边
    DirectionRect rect = directionPointToDirectionRect(_directionPoint, 30, 25);
    if (CGRectContainsPoint(rect.topRect, touchPoint)) {
        _zoomingDirection = Top;
        _zooming = YES;
        return YES;
    }
    if (CGRectContainsPoint(rect.bottomRect, touchPoint)) {
        _zoomingDirection = Bottom;
        _zooming = YES;
        return YES;
    }
    if (CGRectContainsPoint(rect.leftRect, touchPoint)) {
        _zoomingDirection = Left;
        _zooming = YES;
        return YES;
    }
    if (CGRectContainsPoint(rect.rightRect, touchPoint)) {
        _zoomingDirection = Right;
        _zooming = YES;
        return YES;
    }
    // 遍历四个角的坐标,判断是否点击的是四个角
    for (NSInteger i = 0; i < 4; i ++) {
        // 0上左:(0,0) 1上右:(1,0) 2下左:(0,1) 3下右:(1,1)
        CGFloat roundX = i%2 * self.pictureFrame.size.width + self.pictureFrame.origin.x;
        CGFloat roundY = i/2 * self.pictureFrame.size.height + self.pictureFrame.origin.y;
        // 如果在四个角为圆心的圆周内
        if ([self touchInCircleWithPoint:touchPoint circleCenter:CGPointMake(roundX, roundY)]) {
            // 缩放模式
            _zooming = YES;
            // 记录所点的角
            _zoomingIndex = i;
            return YES;
        }
    }
    if (CGRectContainsPoint(self.pictureFrame, touchPoint)) {
        // 拖动模式
        return YES;
    }
    return NO;
}

// 继续触摸跟踪
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchPoint = [touch locationInView:self];
    if (_zooming) {
        // 让剪切框不超过self.bounds的范围
        if (touchPoint.x < 0) {
            touchPoint.x = 0;
        }
        if (touchPoint.y < 0) {
            touchPoint.y = 0;
        }
        if (touchPoint.x > CGRectGetMaxX(self.bounds)) {
            touchPoint.x = CGRectGetMaxX(self.bounds);
        }
        if (touchPoint.y > CGRectGetMaxY(self.bounds)) {
            touchPoint.y = CGRectGetMaxY(self.bounds);
        }
        // 四条边缩放
        CGFloat offsetX = touchPoint.x - _touchedPoint.x;
        CGFloat offsetY = touchPoint.y - _touchedPoint.y;
        CGRect preFrame = self.pictureFrame;
        if (_zoomingDirection == Top) {
            if (offsetY >= preFrame.size.height - self.minHeight) {
                offsetY = preFrame.size.height - self.minHeight;
            } else if (offsetY <= -CGRectGetMinY(preFrame)) {
                offsetY = -CGRectGetMinY(preFrame);
            }
            self.pictureFrame = CGRectMake(preFrame.origin.x, preFrame.origin.y+offsetY, preFrame.size.width, preFrame.size.height-offsetY);
            [self setNeedsDisplay];
            _touchedPoint = touchPoint;
            return YES;
        } else if (_zoomingDirection == Bottom) {
            if (-offsetY >= preFrame.size.height - self.minHeight) {
                // offsetY = self.minHeight - preFrame.size.height;
                // tempFloat = -offsetY
                float tempFloat = preFrame.size.height - self.minHeight;
                offsetY = -tempFloat;
            } else if (offsetY >= self.bounds.size.height - CGRectGetMaxY(preFrame)) {
                offsetY = self.bounds.size.height - CGRectGetMaxY(preFrame);
            }
            self.pictureFrame = CGRectMake(preFrame.origin.x, preFrame.origin.y, preFrame.size.width, preFrame.size.height+offsetY);
            [self setNeedsDisplay];
            _touchedPoint = touchPoint;
            return YES;
        } else if (_zoomingDirection == Left) {
            if (offsetX >= preFrame.size.width - self.minWidth) {
                offsetX = preFrame.size.width - self.minWidth;
            } else if (offsetX <= -CGRectGetMinX(preFrame)) {
                offsetX = -CGRectGetMinX(preFrame);
            }
            self.pictureFrame = CGRectMake(preFrame.origin.x+offsetX, preFrame.origin.y, preFrame.size.width-offsetX, preFrame.size.height);
            [self setNeedsDisplay];
            _touchedPoint = touchPoint;
            return YES;
        } else if (_zoomingDirection == Right) {
            if (-offsetX >= preFrame.size.width - self.minWidth) {
                // offsetX = self.minWidth - preFrame.size.width;
                // tempFloat = -offsetX
                float tempFloat = preFrame.size.width - self.minWidth;
                offsetX = -tempFloat;
            } else if (offsetX >= self.bounds.size.width - CGRectGetMaxX(preFrame)) {
                offsetX = self.bounds.size.width - CGRectGetMaxX(preFrame);
            }
            self.pictureFrame = CGRectMake(preFrame.origin.x, preFrame.origin.y, preFrame.size.width+offsetX, preFrame.size.height);
            [self setNeedsDisplay];
            _touchedPoint = touchPoint;
            return YES;
        }
        // 四个角缩放
        CGPoint diagonalPoint;
        CGPoint cornerPoint;
        switch (_zoomingIndex) {
            case TopLeft: {
                diagonalPoint = _cornerPoint.bottomRightPoint;
                cornerPoint = _cornerPoint.topLeftPoint;
                break;
            }
            case TopRight: {
                diagonalPoint = _cornerPoint.bottomLeftPoint;
                cornerPoint = _cornerPoint.topRightPoint;
                break;
            }
            case BottomLeft: {
                diagonalPoint = _cornerPoint.topRightPoint;
                cornerPoint = _cornerPoint.bottomLeftPoint;
                break;
            }
            case BottomRight: {
                diagonalPoint = _cornerPoint.topLeftPoint;
                cornerPoint = _cornerPoint.bottomRightPoint;
                break;
            }
            default:
                break;
        }
        self.pictureFrame = [self pointToFrame:touchPoint cornerPoint:cornerPoint diagonalPoint:diagonalPoint zoomingIndex:_zoomingIndex];
    } else {
        // 移动剪切框
        // X和Y方向上的偏移量
        CGFloat offsetX = touchPoint.x - _touchedPoint.x;
        CGFloat offsetY = touchPoint.y - _touchedPoint.y;
        CGRect rect = self.pictureFrame;
        rect.origin.x += offsetX;
        rect.origin.y += offsetY;
        // 让剪切框不超过self.bounds的范围
        if (rect.origin.x < 0) {
            rect.origin.x = 0;
        }
        if (rect.origin.y < 0) {
            rect.origin.y = 0;
        }
        if (CGRectGetMaxX(rect) > self.bounds.size.width) {
            rect.origin.x = self.bounds.size.width - self.pictureFrame.size.width;
        }
        if (CGRectGetMaxY(rect) > self.bounds.size.height) {
            rect.origin.y = self.bounds.size.height - self.pictureFrame.size.height;
        }
        self.pictureFrame = rect;
    }
    _touchedPoint = touchPoint;
    [self setNeedsDisplay];
    return YES;
}

// 结束触摸跟踪
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    // 代理回调
    if ([self.delegate respondsToSelector:@selector(photoCutView:shotFrame:)]) {
        [self.delegate photoCutView:self shotFrame:self.pictureFrame];
    }
    // 还原数据
    _touchedPoint = CGPointZero;
    _zooming = NO;
    _zoomingDirection = -1;
}

// 取消触摸跟踪
- (void)cancelTrackingWithEvent:(UIEvent *)event {
    // 还原数据
    _touchedPoint = CGPointZero;
    _zooming = NO;
    _zoomingDirection = -1;
}

// 根据触摸点,计算这个矩形的frame
- (CGRect)pointToFrame:(CGPoint)touching cornerPoint:(CGPoint)corner diagonalPoint:(CGPoint)diagonalPoint zoomingIndex:(CornerIndex)index {
    CGFloat width,height;
    CGPoint origin;
    CGFloat offsetX = touching.x - _touchedPoint.x;
    CGFloat offsetY = touching.y - _touchedPoint.y;
    switch (index) {
        case TopLeft: {
            if (corner.x + offsetX <= 0) {
                offsetX = - corner.x;
            }
            if (corner.y + offsetY <= 0) {
                offsetY = - corner.y;
            }
            origin = CGPointMake(corner.x + offsetX, corner.y + offsetY);
            width = diagonalPoint.x - corner.x - offsetX;
            height = diagonalPoint.y - corner.y - offsetY;
            if (width < self.minWidth) {
                width = self.minWidth;
                origin.x = diagonalPoint.x-self.minWidth;
            }
            if (height < self.minHeight) {
                height = self.minHeight;
                origin.y = diagonalPoint.y-self.minHeight;
            }
            break;
        }
        case TopRight: {
            if (corner.y + offsetY <= 0) {
                offsetY = - corner.y;
            }
            if (corner.x + offsetX >= self.bounds.size.width) {
                offsetX = self.bounds.size.width - corner.x;
            }
            origin = CGPointMake(diagonalPoint.x, corner.y + offsetY);
            width = corner.x + offsetX - diagonalPoint.x;
            height = diagonalPoint.y - corner.y - offsetY;
            if (width < self.minWidth) {
                width = self.minWidth;
                origin.x = diagonalPoint.x;
            }
            if (height < self.minHeight) {
                height = self.minHeight;
                origin.y = diagonalPoint.y - self.minHeight;
            }
            break;
        }
        case BottomLeft: {
            if (corner.x + offsetX <= 0) {
                offsetX = - corner.x;
            }
            if (corner.y + offsetY >= self.bounds.size.height) {
                offsetY = self.bounds.size.height - corner.y;
            }
            origin = CGPointMake(corner.x + offsetX, diagonalPoint.y);
            width = diagonalPoint.x - corner.x - offsetX;
            height = corner.y + offsetY - diagonalPoint.y;
            if (width < self.minWidth) {
                width = self.minWidth;
                origin.x = diagonalPoint.x-self.minWidth;
            }
            if (height < self.minHeight) {
                height = self.minHeight;
                origin.y = diagonalPoint.y;
            }
            break;
        }
        case BottomRight: {
            if (corner.x + offsetX >= self.bounds.size.width) {
                offsetX = self.bounds.size.width - corner.x;
            }
            if (corner.y + offsetY >= self.bounds.size.height) {
                offsetY = self.bounds.size.height - corner.y;
            }
            origin = diagonalPoint;
            width = corner.x + offsetX - diagonalPoint.x;
            height = corner.y + offsetY - diagonalPoint.y;
            if (width < self.minWidth) {
                width = self.minWidth;
                origin.x = diagonalPoint.x;
            }
            if (height < self.minHeight) {
                height = self.minHeight;
                origin.y = diagonalPoint.y;
            }
            break;
        }
        default: {
            width = 0;
            height = 0;
            break;
        }
    }
    CGRect rect = CGRectMake(origin.x, origin.y, width, height);
    return rect;
}

// 判断touchPoint是否在以circleCenter为圆心、半径为touchRadius的圆内
- (BOOL)touchInCircleWithPoint:(CGPoint)touchPoint circleCenter:(CGPoint)circleCenter {
    YBPolarCoordinate polar = decartToPolar(circleCenter, touchPoint);
    if(polar.radius >= touchRadius) {
        return NO;
    } else {
        return YES;
    }
}

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 蒙版层
    [[UIColor colorWithWhite:0.0 alpha:0.3] setFill];
    CGContextFillRect(ctx, self.bounds);
    CGContextClearRect(ctx, self.pictureFrame);
    // 矩形框
    [[UIColor whiteColor] setStroke];
    CGContextAddRect(ctx, self.pictureFrame);
    CGContextStrokePath(ctx);
    CGFloat edge_3 = 3;
    CGFloat edge_20 = 20;
    [[UIColor whiteColor] setFill];
    // 左上
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.topLeftPoint.x-edge_3, _cornerPoint.topLeftPoint.y-edge_3, edge_20, edge_3));
    CGContextFillPath(ctx);
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.topLeftPoint.x-edge_3, _cornerPoint.topLeftPoint.y-edge_3, edge_3, edge_20));
    CGContextFillPath(ctx);
    // 左下
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.bottomLeftPoint.x-edge_3, _cornerPoint.bottomLeftPoint.y, edge_20, edge_3));
    CGContextFillPath(ctx);
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.bottomLeftPoint.x-edge_3, _cornerPoint.bottomLeftPoint.y-edge_20+edge_3, edge_3, edge_20));
    CGContextFillPath(ctx);
    // 右上
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.topRightPoint.x-edge_20+edge_3, _cornerPoint.topRightPoint.y-edge_3, edge_20, edge_3));
    CGContextFillPath(ctx);
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.topRightPoint.x, _cornerPoint.topRightPoint.y-edge_3, edge_3, edge_20));
    CGContextFillPath(ctx);
    // 右下
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.topRightPoint.x-edge_20+edge_3, _cornerPoint.bottomRightPoint.y, edge_20, edge_3));
    CGContextFillPath(ctx);
    CGContextAddRect(ctx, CGRectMake(_cornerPoint.bottomRightPoint.x, _cornerPoint.bottomRightPoint.y-edge_20+edge_3, edge_3, edge_20));
    CGContextFillPath(ctx);
    
    CGFloat direction_30 = 30;
    DirectionRect frame = directionPointToDirectionRect(_directionPoint, direction_30, edge_3);
    // 上
    CGContextAddRect(ctx, frame.topRect);
    CGContextFillPath(ctx);
    // 下
    CGContextAddRect(ctx, frame.bottomRect);
    CGContextFillPath(ctx);
    // 左
    CGContextAddRect(ctx, frame.leftRect);
    CGContextFillPath(ctx);
    // 右
    CGContextAddRect(ctx, frame.rightRect);
    CGContextFillPath(ctx);
    
    CGFloat height_1 = 1/[UIScreen mainScreen].scale;
    // 横一
    CGContextAddRect(ctx, CGRectMake((int)_cornerPoint.topLeftPoint.x, (int)(_cornerPoint.bottomLeftPoint.y-(_cornerPoint.bottomLeftPoint.y-_cornerPoint.topLeftPoint.y)/3*2), _cornerPoint.topRightPoint.x-_cornerPoint.topLeftPoint.x, height_1));
    CGContextFillPath(ctx);
    // 横二
    CGContextAddRect(ctx, CGRectMake((int)_cornerPoint.topLeftPoint.x, (int)(_cornerPoint.bottomLeftPoint.y-(_cornerPoint.bottomLeftPoint.y-_cornerPoint.topLeftPoint.y)/3), _cornerPoint.topRightPoint.x-_cornerPoint.topLeftPoint.x, height_1));
    CGContextFillPath(ctx);
    // 竖一
    CGContextAddRect(ctx, CGRectMake((int)(_cornerPoint.topRightPoint.x-(_cornerPoint.topRightPoint.x-_cornerPoint.topLeftPoint.x)/3*2), (int)_cornerPoint.topRightPoint.y, height_1, _cornerPoint.bottomLeftPoint.y-_cornerPoint.topLeftPoint.y));
    CGContextFillPath(ctx);
    // 竖二
    CGContextAddRect(ctx, CGRectMake((int)(_cornerPoint.topRightPoint.x-(_cornerPoint.topRightPoint.x-_cornerPoint.topLeftPoint.x)/3), (int)_cornerPoint.topRightPoint.y, height_1, _cornerPoint.bottomLeftPoint.y-_cornerPoint.topLeftPoint.y));
    CGContextFillPath(ctx);
}

@end


@implementation YBMath

// 直角坐标转极坐标
YBPolarCoordinate decartToPolar(CGPoint center, CGPoint point){
    double x = point.x - center.x;
    double y = point.y - center.y;
    YBPolarCoordinate polar;
    // pow(x,y); 其作用是计算x的y次方。x、y及函数值都是double型
    // sqrt(double); 计算平方根
    polar.radius = sqrt(pow(x, 2.0) + pow(y, 2.0));
    // double acos(double); 反余弦函数
    polar.angle = acos(x/(sqrt(pow(x, 2.0) + pow(y, 2.0))));
    if (y < 0) {
        polar.angle = 2 * M_PI - polar.angle;
    }
    return polar;
}

// 根据frame计算矩形四个角的坐标
CornerPoint frameToCornerPoint(CGRect frame) {
    CornerPoint corner;
    corner.topLeftPoint = frame.origin;
    corner.topRightPoint = CGPointMake(frame.origin.x+frame.size.width, frame.origin.y);
    corner.bottomLeftPoint = CGPointMake(frame.origin.x, frame.origin.y+frame.size.height);
    corner.bottomRightPoint = CGPointMake(frame.origin.x+frame.size.width, frame.origin.y+frame.size.height);
    return corner;
}

DirectionPoint cornerPointToDirection(CornerPoint corner) {
    DirectionPoint direction;
    direction.top = CGPointMake(corner.topRightPoint.x-(corner.topRightPoint.x-corner.topLeftPoint.x)/2, corner.topRightPoint.y);
    direction.bottom = CGPointMake(corner.topRightPoint.x-(corner.topRightPoint.x-corner.topLeftPoint.x)/2, corner.bottomRightPoint.y);
    direction.left = CGPointMake(corner.topLeftPoint.x, corner.bottomLeftPoint.y-(corner.bottomLeftPoint.y-corner.topLeftPoint.y)/2);
    direction.right = CGPointMake(corner.topRightPoint.x, corner.bottomLeftPoint.y-(corner.bottomLeftPoint.y-corner.topLeftPoint.y)/2);
    return direction;
}

// 宽高是水平方向的,如果是竖直方向则宽高反过来
DirectionRect directionPointToDirectionRect(DirectionPoint drt_point, CGFloat width, CGFloat height) {
    DirectionRect rect;
    rect.topRect = CGRectMake(drt_point.top.x-width/2, drt_point.top.y-height, width, height);
    rect.bottomRect = CGRectMake(drt_point.bottom.x-width/2, drt_point.bottom.y, width, height);
    rect.leftRect = CGRectMake(drt_point.left.x-height, drt_point.left.y-width/2, height, width);
    rect.rightRect = CGRectMake(drt_point.right.x, drt_point.right.y-width/2, height, width);
    return rect;
}

@end

UIImage+FixOrientation
用来处理获取图片的方向并非全是竖屏的问题,不然会导致剪切获取的图片不准确。

#import <UIKit/UIKit.h>

@interface UIImage (FixOrientation)

- (UIImage *)fixOrientation;

@end
#import "UIImage+FixOrientation.h"

@implementation UIImage (FixOrientation)

- (UIImage *)fixOrientation {
    // No-op if the orientation is already correct
    if (self.imageOrientation == UIImageOrientationUp) return self;
    
    // 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 (self.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, self.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }
    
    switch (self.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationDown:
        case UIImageOrientationLeft:
        case UIImageOrientationRight:
            break;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
                                             CGImageGetBitsPerComponent(self.CGImage), 0,
                                             CGImageGetColorSpace(self.CGImage),
                                             CGImageGetBitmapInfo(self.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (self.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.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;
}

@end




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值