zoukankan      html  css  js  c++  java
  • ios 照片编辑的view封装

    转:http://www.cnblogs.com/xiaobaizhu/archive/2013/07/03/3170101.html

    该控件有旋转,缩放,拖动,剪裁的功能,封装成了一个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

  • 相关阅读:
    Hive内部表外部表转化分析
    20130515
    mapred.local.dir
    经典
    hive中巧用正则表达式的贪婪匹配
    做生意十大忌
    股价是最没有用的东西,要看公司基本面和盈利
    textView文本不同颜色
    Android中扫描wifi热点
    android 与 PC的socket通信
  • 原文地址:https://www.cnblogs.com/jackljf/p/4768593.html
Copyright © 2011-2022 走看看