分享

ios 照片编辑的view封装

 叹落花 2015-04-02

该控件有旋转,缩放,拖动,剪裁的功能,封装成了一个ImageCropperView类

需要导入的库:QuartzCore.framework

ImageCopperView.h

复制代码
#import <UIKit/UIKit.h>

@protocol ImageCropperDelegate;

@interface ImageCropperView : UIView {
    UIImageView *imageView;
    
    id <ImageCropperDelegate> delegate;
}

@property (nonatomic, retain) UIImage *image;
@property (nonatomic, retain) UIImage *croppedImage;

@property (nonatomic, assign) id <ImageCropperDelegate> delegate;

@property (nonatomic, assign) BOOL enable;
@property (nonatomic, assign) BOOL isPaning;

- (void)setup;
- (void)finishCropping;
- (void)reset;

@end

@protocol ImageCropperDelegate <NSObject>
- (void)changeMoveStateWithCropper:(UIPanGestureRecognizer*)gesture Crop:(ImageCropperView*)imageCrop;
@end
复制代码

ImageCopperView.m

复制代码
#import "ImageCropperView.h"
#import <QuartzCore/QuartzCore.h>
#include <math.h>
#import "UIImage+Rotation.h"

@interface ImageCropperView()
{
    @private
    CGSize _originalImageViewSize;
}

@property (nonatomic, retain) UIImageView *imageView;
@end

@implementation ImageCropperView

@synthesize imageView, image = _image, delegate, croppedImage;

- (void)setup
{
    _enable = YES;
    self.clipsToBounds = YES;
    self.backgroundColor = [UIColor clearColor];
    
    self.imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)] autorelease];
    imageView.userInteractionEnabled = YES;
    [self addSubview:imageView];
    
    UIRotationGestureRecognizer *rotateGes = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateImage:)];
    [imageView addGestureRecognizer:rotateGes];
    [rotateGes release];
    
    UIPinchGestureRecognizer *scaleGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scaleImage:)];
    [imageView addGestureRecognizer:scaleGes];
    [scaleGes release];
    
    UIPanGestureRecognizer *moveGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveImage:)];
    [moveGes setMinimumNumberOfTouches:1];
    [moveGes setMaximumNumberOfTouches:1];
    [imageView addGestureRecognizer:moveGes];
    [moveGes release];
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    
    if (self) {
        self.frame = frame;
        [self setup];
    }
    
    return self;
}

float _lastTransX = 0.0, _lastTransY = 0.0;
- (void)moveImage:(UIPanGestureRecognizer *)sender
{
    _isPaning = YES;
    if (delegate&&[delegate respondsToSelector:@selector(changeMoveStateWithCropper:Crop:)]) {
        [delegate changeMoveStateWithCropper:sender Crop:self];
    }else{
        return;
    }
    if (sender.numberOfTouches != 1||_enable == NO) {
        return;
    }
    //获取在视图中手势的触点位置
    CGPoint translatedPoint = [sender translationInView:self];

    if([sender state] == UIGestureRecognizerStateBegan) {
        _lastTransX = 0.0;
        _lastTransY = 0.0;
    }
    
    CGAffineTransform trans = CGAffineTransformMakeTranslation(translatedPoint.x - _lastTransX, translatedPoint.y - _lastTransY);
    //CGAffineTransformConcat将imageView.transform和trans两个动画连续起来
    CGAffineTransform newTransform = CGAffineTransformConcat(imageView.transform, trans);
    _lastTransX = translatedPoint.x;
    _lastTransY = translatedPoint.y;
    NSLog(@"_lastTransX==%f,_lastTransY==%f",_lastTransX,_lastTransY);
    imageView.transform = newTransform;
}

float _lastScale = 1.0;
- (void)scaleImage:(UIPinchGestureRecognizer *)sender
{
    _isPaning = NO;
    if (sender.numberOfTouches != 2||_enable == NO) {
        return;
    }
    
    if([sender state] == UIGestureRecognizerStateBegan) {
        
        _lastScale = 1.0;
        return;
    }
    
    CGFloat scale = [sender scale]/_lastScale;
    
    CGAffineTransform currentTransform = imageView.transform;
    CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
    [imageView setTransform:newTransform];
    
    _lastScale = [sender scale];
}

float _lastRotation = 0.0;
- (void)rotateImage:(UIRotationGestureRecognizer *)sender
{
    _isPaning = NO;
    if (sender.numberOfTouches != 2||_enable == NO) {
        return;
    }
    
    if([sender state] == UIGestureRecognizerStateEnded) {
        
        _lastRotation = 0.0;
        return;
    }
    
    CGFloat rotation = -_lastRotation + [sender rotation];
    
    CGAffineTransform currentTransform = imageView.transform;
    CGAffineTransform newTransform = CGAffineTransformRotate(currentTransform,rotation);
    [imageView setTransform:newTransform];
    
    _lastRotation = [sender rotation];
    
}

- (void)setImage:(UIImage *)image
{
    if (_image != image) {
        _image = [image retain];
    }
    
    float _imageScale = self.frame.size.width / image.size.width;
    self.imageView.frame = CGRectMake(0, 0, image.size.width*_imageScale, image.size.height*_imageScale);
    _originalImageViewSize = CGSizeMake(image.size.width*_imageScale, image.size.height*_imageScale);
    imageView.image = image;
    imageView.center = CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0);
}

- (void)finishCropping {
    float zoomScale = [[self.imageView.layer valueForKeyPath:@"transform.scale.x"] floatValue];
    float rotate = [[self.imageView.layer valueForKeyPath:@"transform.rotation.z"] floatValue];
    
    float _imageScale = _image.size.width/_originalImageViewSize.width;
    CGSize cropSize = CGSizeMake(self.frame.size.width/zoomScale, self.frame.size.height/zoomScale);
    CGPoint cropperViewOrigin = CGPointMake((0.0 - self.imageView.frame.origin.x)/zoomScale,
                                            (0.0 - self.imageView.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 = [self.image imageRotatedByRadians:rotate];
    CGImageRef tmp = CGImageCreateWithImageInRect([rotInputImage CGImage], CropRectinImage);
    self.croppedImage = [UIImage imageWithCGImage:tmp scale:self.image.scale orientation:self.image.imageOrientation];
    CGImageRelease(tmp);
}

- (void)reset
{
    self.imageView.transform = CGAffineTransformIdentity;
}

- (void)dealloc {
    self.image = nil;
    self.croppedImage = nil;
    self.imageView = nil;
    
    [super dealloc];
}

@end
复制代码

对UIImage添加了一个category

UIImage+Rotation.h

复制代码
#import <UIKit/UIKit.h>

@interface UIImage (Rotation)

- (UIImage *)imageRotatedByRadians:(CGFloat)radians;
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;

@end
复制代码

UIImage+Rotation.m

复制代码
#import "UIImage+Rotation.h"

/************
 角度=弧度/Pi*180
 弧度=角度/180*Pi
 *************/

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

@implementation UIImage (Rotation)

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

- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees
{
    /*****
     CGAffineTransformMakeRotation
     通过指定角度来创建一个旋转矩阵
     CGAffineTransformRotate
     在已存在的矩阵中使用旋转
     *****/
    UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
    CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
    //给view旋转角度
    rotatedViewBox.transform = t;
    CGSize rotatedSize = rotatedViewBox.frame.size;
    [rotatedViewBox release];
    //开始编辑图形上下文
    UIGraphicsBeginImageContext(rotatedSize);
    //定义一个图形上下文
    CGContextRef bitmap = UIGraphicsGetCurrentContext();
    //沿x轴移动rotatedSize.width/2,y轴移动rotatedSize.height
    CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
    //以原点(左下角)为中心旋转DegreesToRadians(degrees)弧度,正角度逆时针,负角度顺时针
    CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
    //缩放x轴,y轴方向
    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
    UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
    //结束绘制
    UIGraphicsEndImageContext();
    return resImage;  
}

@end;
复制代码

ViewController.m

复制代码
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#import "ImagecropperView.h"

@interface ViewController ()<ImageCropperDelegate>{
}

@property (nonatomic, retain) IBOutlet ImageCropperView *cropper;
@property (nonatomic, retain) IBOutlet UIImageView *result;
@property (retain, nonatomic) IBOutlet UIImageView *resultSecond;
@property (nonatomic, retain) IBOutlet UIButton *btn;
@property (retain, nonatomic) IBOutlet ImageCropperView *cropperSecond;
@property (retain, nonatomic) IBOutlet UIButton *cropButton;

@end

@implementation ViewController
//@synthesize cropper, result, btn;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    _cropper.layer.borderWidth = 1.0;
    _cropper.layer.borderColor = [UIColor blueColor].CGColor;
    _cropper.delegate = self;
    [_cropper setup];
    _cropper.image = [UIImage imageNamed:@"2.jpg"];
    [_btn addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];
    
    _cropperSecond.layer.borderColor = [UIColor blackColor].CGColor;
    _cropperSecond.layer.borderWidth = 2.0;
    _cropperSecond.delegate = self;
    [_cropperSecond setup];
    _cropperSecond.image = [UIImage imageNamed:@"1.jpg"];
    [_cropButton addTarget:self action:@selector(tapCropButton) forControlEvents:UIControlEventTouchUpInside];
}

- (void)buttonClicked
{
    if ([_btn.currentTitle isEqualToString:@"Crop1"]) {
        [_cropper finishCropping];//保存
        _result.image = _cropper.croppedImage;
        _cropper.hidden = YES;
        [_btn setTitle:@"Back" forState:UIControlStateNormal];
        [_btn setTitle:@"Back" forState:UIControlStateHighlighted];
    }else
    {
        [_cropper reset];
        _cropper.hidden = NO;
        [_btn setTitle:@"Crop1" forState:UIControlStateNormal];
        [_btn setTitle:@"Crop1" forState:UIControlStateHighlighted];
        _result.image = nil;
    }
    _cropperSecond.enable = YES;
    _cropper.enable = YES;
}

- (void)tapCropButton{
    if ([_cropButton.currentTitle isEqualToString:@"Crop2"]) {
        [_cropperSecond finishCropping];
        _cropperSecond.enable = NO;
        _resultSecond.image = _cropperSecond.croppedImage;
        _cropperSecond.hidden = YES;
        [_cropButton setTitle:@"Back" forState:UIControlStateNormal];
        [_cropButton setTitle:@"Back" forState:UIControlStateHighlighted];
    }else
    {
        [_cropperSecond reset];
        
        _cropperSecond.hidden = NO;
        [_cropButton setTitle:@"Crop2" forState:UIControlStateNormal];
        [_cropButton setTitle:@"Crop2" forState:UIControlStateHighlighted];
        _resultSecond.image = nil;
    }
    _cropperSecond.enable = YES;
    _cropper.enable = YES;
}

#pragma mark - ImageCropperDelegate
- (void)changeMoveStateWithCropper:(UIPanGestureRecognizer*)gesture Crop:(ImageCropperView*)imageCrop{
    if (gesture.state == UIGestureRecognizerStateEnded) {        
        NSLog(@"点击编辑器结束,两个_cropper都可以进行编辑");
        _cropperSecond.enable = YES;
        _cropper.enable = YES;
    }
}


- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
{
//判断点击在控件上
    UITouch *touch = [touches anyObject];
    if ([_cropper pointInside:[touch locationInView:_cropper] withEvent:nil]) {
        NSLog(@"_cropper1 被触摸,禁用_cropper2");
        _cropperSecond.enable = NO;
    }else if ([_cropperSecond pointInside:[touch locationInView:_cropperSecond] withEvent:nil]){
        NSLog(@"_cropper2 被触摸,禁用_cropper1");
        _cropper.enable = NO;
    }
}

- (void)dealloc {
    [_cropperSecond release];
    [_cropButton release];
    [_resultSecond release];
    [super dealloc];
}
- (void)viewDidUnload {
    [self setCropperSecond:nil];
    [self setCropButton:nil];
    [self setResultSecond:nil];
    [super viewDidUnload];
}
@end
复制代码

下面是截图

最后要注意,因为我是用xib做的,拖上去的UIView要将其Class改成ImageCropperView

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多