亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

IOS 照片編輯的view封裝的實例詳解

2020-07-26 02:43:39
字體:
來源:轉載
供稿:網友

IOS 照片編輯的view封裝

該控件有旋轉,縮放,拖動,剪裁的功能,封裝成了一個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

如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品在线网站| 欧美成人午夜剧场免费观看| 97视频在线观看免费高清完整版在线观看| 午夜欧美大片免费观看| 久久久久久久久网站| 精品久久久久久久久国产字幕| 日韩av综合中文字幕| 精品国产电影一区| 欧美激情视频三区| 91大神在线播放精品| 欧美一级电影免费在线观看| 亚洲国内精品视频| 最近更新的2019中文字幕| 亚洲欧美日韩一区二区三区在线| 亚洲a在线观看| 精品国产欧美成人夜夜嗨| 欧美国产欧美亚洲国产日韩mv天天看完整| 色综合亚洲精品激情狠狠| 福利一区视频在线观看| 欧美一级电影在线| 亚洲第一福利视频| 欧美一区二区三区精品电影| 亚洲欧洲国产一区| 最近2019中文字幕一页二页| 久久久久久国产三级电影| 欧美在线xxx| 国产成人一区二区三区小说| 亚洲高清一区二| 91久久精品在线| 日韩网站免费观看| 亚洲欧洲成视频免费观看| 久99九色视频在线观看| 精品亚洲国产视频| 欧美专区国产专区| 欧美日韩国产中字| 久久久久久国产精品| 91久久久久久国产精品| 国产日韩亚洲欧美| 韩国19禁主播vip福利视频| 国内精品一区二区三区四区| 日韩欧美亚洲范冰冰与中字| 欧美日韩中国免费专区在线看| 丝袜情趣国产精品| 久久成人18免费网站| 国产成人精品一区二区三区| 欧美孕妇性xx| 久久97精品久久久久久久不卡| 国产精品尤物福利片在线观看| 在线观看精品自拍私拍| 日韩在线观看你懂的| 国产精品久久久久久久美男| 亚洲天堂男人天堂女人天堂| 亚洲天堂av综合网| 国产性猛交xxxx免费看久久| 中文字幕亚洲第一| 精品亚洲一区二区三区| 欧美性xxxxxx| 亚洲人成电影在线观看天堂色| 日韩欧美中文免费| 国产精品极品美女在线观看免费| 尤物九九久久国产精品的特点| 国产精品第3页| 欧美激情亚洲综合一区| 国产精品青草久久久久福利99| 欧美在线观看日本一区| 精品久久久久久久久久ntr影视| 国产美女搞久久| 国色天香2019中文字幕在线观看| 91香蕉电影院| 久久久久久久久久国产| 亚洲新声在线观看| 久久亚洲精品小早川怜子66| 欧美激情xxxx| 日韩av在线网址| 国产精品视频在线播放| 国产视频精品免费播放| 日本久久久久久久| 国产在线日韩在线| 欧美中在线观看| 日日噜噜噜夜夜爽亚洲精品| 欧美性高潮床叫视频| 97国产suv精品一区二区62| 国产成人精品在线观看| 国产91精品久久久| 最好看的2019的中文字幕视频| 精品国产一区二区三区久久久狼| 日韩中文字幕欧美| 九九热精品视频| 欧美性感美女h网站在线观看免费| 欧美日韩福利在线观看| 国产福利精品视频| 亚洲tv在线观看| 精品久久久一区二区| 成人午夜小视频| 欧美性猛交xxxxx免费看| 亲爱的老师9免费观看全集电视剧| 欧美激情国产精品| 国产精品视频久久久| 美女久久久久久久| 欧美成人国产va精品日本一级| 日韩成人久久久| 欧美中文在线观看| 欧美综合第一页| 97av在线影院| 久久久女女女女999久久| 91精品国产乱码久久久久久久久| 亚洲天堂成人在线视频| 欧美日韩中文字幕| 国产综合香蕉五月婷在线| 国产伦精品一区二区三区精品视频| 欧美日韩精品在线观看| 色老头一区二区三区在线观看| 国产精品揄拍500视频| 欧美激情一级精品国产| 亚洲美女av在线| 久久精品成人欧美大片古装| 久久久www成人免费精品| 久久久久久国产精品美女| 精品久久香蕉国产线看观看亚洲| 日韩av一区在线| 日韩欧美高清在线视频| 538国产精品一区二区免费视频| 国产精品久久激情| 亚洲最新中文字幕| 国产噜噜噜噜久久久久久久久| 日韩电影大全免费观看2023年上| 国产精品久久久久久久av大片| 欧美日韩国产中文精品字幕自在自线| 欧美成人全部免费| 国产精品大陆在线观看| 久久av红桃一区二区小说| 91网站在线看| 精品国模在线视频| 欧美成aaa人片免费看| 国产中文日韩欧美| 日韩av在线播放资源| 国产精品美女www爽爽爽视频| 日本久久久久久久久| 亚洲精品国产品国语在线| 北条麻妃一区二区在线观看| 国产精品国产福利国产秒拍| 欧美另类在线观看| 国产美女久久精品香蕉69| 欧美夫妻性生活xx| 久久人91精品久久久久久不卡| 成人美女av在线直播| 欧美激情欧美激情在线五月| 亚洲成人xxx| 亚洲精品国产suv| 成人高清视频观看www| 国产精品一区二区久久久| 国产精品揄拍一区二区| 亚洲乱码一区av黑人高潮| 久久精品国产亚洲7777| 亚洲在线观看视频网站| 亚洲色无码播放| 久久久亚洲国产| 精品偷拍各种wc美女嘘嘘| 亚洲美女精品成人在线视频| 成人午夜激情免费视频| 久久免费视频在线| 日韩精品亚洲精品| 夜夜嗨av色一区二区不卡| 日韩电影中文字幕av|