做一个属于自己的照片编辑器

使用过UIImagePickerController的童鞋们都知道,iOS在从相册或者摄像头后选择照片后可以编辑(选择照片的一部分剪切下来),只需要将UIImagePickerController的allowsEditing属性设为YES即可。哇,so easy!

真的如此简单吗?你如果这样想就可以不要继续看下去了。

用过的童鞋应该都会这么认为(至少我是这么认为)系统的那个渣渣真是他妈的弱爆了,主要体现在如下两点:
1、只能裁剪正方形;
2、照片边缘部分可能无法移动到裁剪区域。

哦,怎么办,产品狗就要给他弄一个长方形,甚至裁剪一个不规则形状。

哥前两天就遇到了这么狗血的事情,怎么办?哥百度、谷歌、github都了个遍,好像没找到有什么卵用的东西,于是乎只能自己动手写一个了。

好了,进入正题。如何实现一个可以剪切任意形状的图片编辑器?
需要考虑如下两个问题:
1、用户如何操作,以及界面的实现
2、如何裁剪。

首先解决第一个问题:
系统的图片编辑器是选中框不能移动,可以通过缩放和移动图片,从而确定需要选中的图片区域,此方法的优点是图片可以缩放,小图片可以放大来看清楚。但说真的,我不习惯这种操作。
我采取的方式是,将图片放在确定的位置,通过缩放和移动选中框而确定选中的图片区域。
实现如下:为了实现不规则形状选择时,未选中部分也有半透明阴影,通过在遮挡视图上绘制而成:

遮挡视图.h

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, MGCEditSelectImageViewShapeStyle) {
    MGCEditSelectImageViewShapeStyle_rect,
    MGCEditSelectImageViewShapeStyle_circle,
};

// 遮挡视图(目前只支持矩形和圆形,其它形状可以类似实现)
@interface MGCEditSelectImageView : UIView
@property (nonatomic, readonly) CGFloat width;
@property (nonatomic, readonly) CGFloat height;

@property (nonatomic, readonly) MGCEditSelectImageViewShapeStyle style;

/**
 *  画形状
 *
 *  @param width  宽度、长半径
 *  @param height 高度、短半径
 *  @param style  形状类型,当画矩形时,若width或者height中的一个为0,那么画正方形,当画椭圆时,若width或者height为0时,画圆
 */
- (void)drawShapeWithWidth:(CGFloat)width height:(CGFloat)height shapeStyle:(MGCEditSelectImageViewShapeStyle)style;

@end

遮挡视图.m

#import "MGCEditSelectImageView.h"

@interface MGCEditSelectImageView ()

@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;

@property (nonatomic, assign) MGCEditSelectImageViewShapeStyle style;

@end

@implementation MGCEditSelectImageView

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (self.superview) {

        // 绘制边框,
        CGContextAddRect(context, CGRectMake(-self.frame.origin.x - 1, -self.frame.origin.y - 1, self.superview.frame.size.width + 2, self.superview.frame.size.height + 2));
    }else{
        CGContextAddRect(context, self.bounds);
    }

    [self drawShapeContext:context];
    // 设置触笔颜色
    [[UIColor whiteColor] setStroke];
    // 将未选中部分蛇者为阴影半透明颜色
    [[[UIColor blackColor] colorWithAlphaComponent:0.6] setFill];
    CGContextDrawPath(context, kCGPathEOFillStroke);

}

#pragma mark - pravate
// 绘制形状
- (void)drawShapeContext:(CGContextRef)context
{
    if (self.width || self.height) {
        if (self.width <= 0 && self.height > 0) {
            self.width = self.height;
        }else if (self.height <= 0 && self.width > 0){
            self.height = self.width;
        }

        CGFloat x = (self.frame.size.width - self.width) / 2;
        CGFloat y = (self.frame.size.height - self.height) / 2;

        CGRect rect = CGRectMake(x, y, self.width, self.height);

        if (self.style == MGCEditSelectImageViewShapeStyle_rect) {
        // 绘制矩形
            CGContextAddRect(context, rect);
        }else if (self.style == MGCEditSelectImageViewShapeStyle_circle){
        // 绘制圆形
            CGContextAddEllipseInRect(context, rect);
        }
    }

}

#pragma mark - public
- (void)drawShapeWithWidth:(CGFloat)width height:(CGFloat)height shapeStyle:(MGCEditSelectImageViewShapeStyle)style
{
    self.width = width;
    self.height = height;
    self.style = style;

    [self setNeedsDisplay];
}

@end

遮挡视图已经解决,嘿,为什么把选中部分的形状绘制在中心?因为这样的话,在移动选择区域时只需要移动整个遮挡视图,而无需每次都计算绘制形状的位置,为了保证无论如何移动,遮挡视图都会覆盖整个父视图,因此,该遮挡视图的大小必选是父视图大小的9倍。

接下来看控制器代码:
.h

#import <UIKit/UIKit.h>

#import "MGCEditSelectImageView.h"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值