文档章节

图片裁剪

A
 AAAAdler
发布于 2015/02/13 16:56
字数 734
阅读 697
收藏 11

项目中要用到,选取图库或者拍照的图片,然后截取固定的尺寸作为头像,当时是使用第三方库GKImagePicker,但是其中的bug,弄了半天也修不了,并且感觉它的这个功能的代码做的太复杂了,所有自己写了一个类似功能的。

这里主要记录过程中发现的一些东西:

  1. scrollview缩放后,其frame不变,sourceImage的frame会被缩放到需要的大小,scrollview的contentsize不论之前是多少,在缩放后,会和sourceImage的frame一样大小。

  2. 截取内容尺寸大小,需要乘以一个比例,这个比例是image的frame大小和image实际图像大小的比例。

  3. scrollview如果contentoffset是处于边界了,就无法移动,不论加在上面的sourceImage有多大,都会被弹回,而contentsize的默认坐标也只能是(0,0)。

@interface CropImageView : UIView<UIScrollViewDelegate> {
    UIImageView* _sourceImage;
    UIScrollView* _scrollView;
    UIView* _maskView;
    
    CGFloat _addWidth;
    CGFloat _addHeight;
}

@property(nonatomic, strong) UIImage* inputImage;
@property(nonatomic, strong) UIImage* outputImage;
// 裁剪需要的尺寸,会居中显示
@property(nonatomic, assign) CGSize cropSize;
#define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
#define SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height

#import "CropImageView.h"

@implementation CropImageView

- (UIImage *)outputImage {
    CGFloat w_faktor = _sourceImage.image.size.width / _sourceImage.frame.size.width;
    CGFloat h_faktor = _sourceImage.image.size.height / _sourceImage.frame.size.height;
    
    CGFloat x = _scrollView.contentOffset.x * w_faktor;
    CGFloat y = _scrollView.contentOffset.y * h_faktor;
    
    CGRect myImageRect = CGRectMake(x, y, _cropSize.width * w_faktor, _cropSize.height * h_faktor);
    
    CGImageRef sourceImageRef = [_sourceImage.image CGImage];
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, myImageRect);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    CGImageRelease(newImageRef);
    
    return newImage;
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    return _scrollView;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    _scrollView = [[UIScrollView alloc] init];
    _scrollView.backgroundColor = [UIColor greenColor];
    // scrollview的frame这里只是暂时设置
    _scrollView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    _scrollView.clipsToBounds = NO;
    _scrollView.delegate = self;
    _scrollView.minimumZoomScale = 1.0f;
    _scrollView.maximumZoomScale = 20.0f;
    [_scrollView setZoomScale:1.0f];
    [self addSubview:_scrollView];
    
    CGFloat resultHeight, resultWidth;
    // 把图片进行压缩,但要比例不变
    if (_inputImage.size.width > SCREEN_WIDTH) {
        if (_inputImage.size.width > _inputImage.size.height) {
            CGFloat faktor = _inputImage.size.width / SCREEN_WIDTH;
            resultWidth = SCREEN_WIDTH;
            resultHeight = _inputImage.size.height / faktor;
        }
    } else if (_inputImage.size.height > SCREEN_HEIGHT) {
        if (_inputImage.size.height > _inputImage.size.width) {
            CGFloat faktor = _inputImage.size.height / SCREEN_HEIGHT;
            resultHeight = SCREEN_HEIGHT;
            resultWidth = _inputImage.size.width / faktor;
        }
    } else {
        resultWidth = _inputImage.size.width;
        resultHeight = _inputImage.size.height;
    }
    // 计算位置,也要居中
    CGFloat x = (_scrollView.frame.size.width - resultWidth) / 2;
    CGFloat y = (_scrollView.frame.size.height - resultHeight) / 2;
    // 补差,因为裁剪的显示位置也会居中,那如何让image的各个部分都可以滚动到裁剪位置内呢,这就需要补差
    CGFloat addWidth = 0, addHeight = 0;
    if (resultWidth > _cropSize.width) {
        addWidth = (resultWidth - _cropSize.width) / 2;
    }
    if (resultHeight > _cropSize.height) {
        addHeight = (resultHeight - _cropSize.height) / 2;
    }
    
    _addWidth = addWidth;
    _addHeight = addHeight;
    
    _scrollView.frame = CGRectMake(x, y, resultWidth, resultHeight);
    
    _scrollView.contentSize = CGSizeMake(resultWidth + 2 * addWidth, resultHeight + 2 * addHeight);
    
    _sourceImage = [[UIImageView alloc] initWithImage:_inputImage];
    _sourceImage.backgroundColor = [UIColor brownColor];
    _sourceImage.frame = CGRectMake(addWidth, addHeight, resultWidth, resultHeight);
    [_scrollView addSubview:_sourceImage];
    
    _scrollView.contentOffset = CGPointMake(addWidth, addHeight);
    
    // 最上层的view,用来作为遮罩
    _maskView = [[UIView alloc] initWithFrame:self.bounds];
    _maskView.backgroundColor = [UIColor blackColor];
    _maskView.alpha = 0.6;
    _maskView.userInteractionEnabled = NO;
    [self addSubview:_maskView];
    
    x = (SCREEN_WIDTH - _cropSize.width) / 2;
    y = (SCREEN_HEIGHT - _cropSize.height) / 2;
    // 显示出裁剪位置尺寸
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    // 这个方法在ios7下有问题,会变成三角形,具体原因不知,替代方法是换成圆角矩形,把圆角角度设为0
    // [path appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(x, y, _cropSize.width, _cropSize.height) byRoundingCorners:0 cornerRadii:CGSizeZero] bezierPathByReversingPath]];
    [path appendPath:[[UIBezierPath bezierPathWithRect:CGRectMake(x, y, _cropSize.width, _cropSize.height)] bezierPathByReversingPath]];
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    
    shapeLayer.path = path.CGPath;
    _maskView.layer.mask = shapeLayer;
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _sourceImage;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
    
    CGSize recontentSize = CGSizeMake(_scrollView.contentSize.width + _addWidth * 2, _scrollView.contentSize.height + _addHeight * 2);
    _scrollView.contentSize = recontentSize;
}

© 著作权归作者所有

上一篇: ios简易抽屉效果
下一篇: Nimbus初理解
A
粉丝 3
博文 26
码字总数 23250
作品 0
广州
私信 提问
SimpleCrop 支持任意角度旋转的图片裁剪组件

简介 :github.com/newbieYoung… 是一个在功能和交互上参考 IOS 系统的原生图片裁剪功能并支持任意角度旋转的 Web 图片裁剪组件; 左侧是 IOS 系统相册中原生的图片裁剪功能,右侧为 Simple...

NewbieYoung
05/01
0
0
php图片裁剪--Tclip

名字说明: T,头像之意。 clip,读[klip],译为裁剪。 Tclip,是一个头像自动识别,php图片裁剪项目。 概要: 用于图片裁剪。有以下特点: 1.能进行人脸识别。图片中有人脸,将自动视为人脸...

exinnet
2013/07/23
8.1K
2
【前端】图片裁剪(二)Jcrop实现裁剪

学着做自己,并优雅的放手不属于自己的。 前一篇文章已经跟大家讲述了如何利用JavaScript实现Web端图片裁剪功能。可能对大多数人来说,利用JavaScript去实现裁剪功能比较费事,那这一篇文章将...

zrunker
2017/10/25
0
0
apiCloud中图片裁剪模块FNImageClip的使用

思路 1.获取需裁剪图片的地址 2.跳转到裁剪页面 3.裁剪成功返回新图片地址 4.替换原有图片地址 增加修饰和事件 上面是动态生成的图片html布局数据,增加一个id标识,增加一个点击事件 打开裁剪...

桃子红了呐
2018/01/07
0
0
如何在微信公众号开发中实现图片裁剪

接触微信公众号开发已经有一段时间了,发现其实和网页开发差不多,但是因为浏览器的不同,自己也碰过一些坑,其中就有怎么实现图片裁剪功能。 一开始我是用PC端的思路去做的,首先在本地获取...

豆花饭烧土豆
2016/08/17
420
0

没有更多内容

加载失败,请刷新页面

加载更多

代理模式之JDK动态代理 — “JDK Dynamic Proxy“

动态代理的原理是什么? 所谓的动态代理,他是一个代理机制,代理机制可以看作是对调用目标的一个包装,这样我们对目标代码的调用不是直接发生的,而是通过代理完成,通过代理可以有效的让调...

code-ortaerc
今天
5
0
学习记录(day05-标签操作、属性绑定、语句控制、数据绑定、事件绑定、案例用户登录)

[TOC] 1.1.1标签操作v-text&v-html v-text:会把data中绑定的数据值原样输出。 v-html:会把data中值输出,且会自动解析html代码 <!--可以将指定的内容显示到标签体中--><标签 v-text=""></......

庭前云落
今天
8
0
VMware vSphere的两种RDM磁盘

在VMware vSphere vCenter中创建虚拟机时,可以添加一种叫RDM的磁盘。 RDM - Raw Device Mapping,原始设备映射,那么,RDM磁盘是不是就可以称作为“原始设备映射磁盘”呢?这也是一种可以热...

大别阿郎
今天
12
0
【AngularJS学习笔记】02 小杂烩及学习总结

本文转载于:专业的前端网站☞【AngularJS学习笔记】02 小杂烩及学习总结 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy ......

前端老手
昨天
16
0
Linux 内核的五大创新

在科技行业,创新这个词几乎和革命一样到处泛滥,所以很难将那些夸张的东西与真正令人振奋的东西区分开来。Linux内核被称为创新,但它又被称为现代计算中最大的奇迹,一个微观世界中的庞然大...

阮鹏
昨天
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部