[Swift3] 对图片进行裁剪

来源:互联网 发布:金薇内衣网络传销吗 编辑:程序博客网 时间:2024/04/30 07:21

如果单独的对已有图片进行裁剪,可以使用系统自带的函数,但是这个函数需要对图片进行一些处理。我这里自己实现了一个对UIImage的extension。

extension UIImage {func subImage(rect: CGRect) -> UIImage? {let cgImage = self.cgImage!  // 需要先转换成CGImagelet image= cgImage.cropping(to: rect)  // 要注意rect的大小和位置不要超出image的范围return image}}
这种情况需要注意rect的大小和位置,我这里要实现的是用户在自己创建的UIImageView上对图片自行裁剪。

用户画图部分我选择用CAShapeLayer实现,首先对其写一个扩展,对一些数据进行预设,这样以后定义的时候就不需要每次都进行设置了

extension CAShapeLayer {        class func defaultShapeLayer() -> CAShapeLayer {        let shapeLayer = CAShapeLayer()        let frame = CGRect(x: 0, y: 0, width: screenW, height: bottomImageH)  // 这里的frame是定义的用户绘图的frame        shapeLayer.frame = frame        shapeLayer.strokeColor = UIColor.red.cgColor  // 线的颜色        shapeLayer.fillColor = UIColor.clear.cgColor // 填充色为透明        shapeLayer.lineWidth = 2  // 线宽                return shapeLayer    }    }

由于用户是通过按下手指,滑动屏幕来描绘矩形,所以这个矩形的创建使用开始点和结束点这两个点创建比较方便,但是系统没有这个函数,所以接下来对CGRect进行扩展

init(startPoint: CGPoint, endPoint: CGPoint) {        self.init(x: startPoint.x, y: startPoint.y, width: endPoint.x - startPoint.x, height: endPoint.y - startPoint.y)    }
这样一些准备工作就完成了,接下来从用户开始画矩形开始

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {  // 这个函数是当用户开始触摸这个View时调用        if let touch = touches.first {            shapeLayer?.removeFromSuperlayer()  // 由于设定只能有一个矩形,所以这个shapeLayer作为了我的View的属性,当触屏开始时先将原有的矩形移除            shapeLayer = CAShapeLayer.defaultShapeLayer()            startPoint = touch.location(in: self)  // 记录开始点        }    }
然后是用户手指在屏幕上移动时,这个矩形要随时进行移动,但是要注意一点,矩形的范围不可以超过View的范围。即使手指已经超出那个范围。


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {  // 当用户手指移动时        if let touch = touches.first {            endPoint = touch.location(in: self)            endPoint.y = endPoint.y < 0 ? 0 : endPoint.y            endPoint.y = endPoint.y > bottomImageH ? bottomImageH : endPoint.y            shapeLayer.path = UIBezierPath(rect: CGRect(startPoint: startPoint, endPoint: endPoint)).cgPath  // 设置shapeLayer的path            self.layer.addSublayer(shapeLayer)  // 实时显示矩形        }    }

结束之后就可以通过这两个点生成的矩形进行裁剪啦。

但是,裁剪的时候,重点,也是坑点,来了


由于imageView的大小和图片的大小不一致,所以图片会有一些拉伸。也就是说用户在imageView上画的矩形和image上对应的矩形很有可能是不一致的。

打个比方,我们的图片是一个50x50的正方形,但是你的imageView却是一个100x150的矩形,如果用户将整个矩形都选中,我们直接使用这个100x150的矩形在原正方形上截图,就会出现问题。所以我们需要通过一定的算法将这个100x150的矩形转换成50x50的正方形。这样最开始的那个扩展就需要进行一定的调整

//  这是对imageView写的扩展,所以有些地方会与一开始那个不一样

func subImage(rect: CGRect) -> UIImage? {        let sourceImage: CGImage = (self.image?.cgImage!)!        let widthScale = CGFloat(sourceImage.width) / self.frame.width  // 计算宽度比        let heightScale = CGFloat(sourceImage.height) / self.frame.height  // 计算高度比        let originPoint = CGPoint(x: rect.origin.x * widthScale, y: rect.origin.y * heightScale)  // 计算原点(startPoint)的偏移量        let size = CGSize(width: rect.width * widthScale, height: rect.height * heightScale)  // 计算size        let rect = CGRect(origin: originPoint, size: size)  // 在image上对应的矩形        let image = sourceImage.cropping(to: rect)                return image == nil    }


这样就可以得到对应的图片了,之后就可以对这个图片进行操作了。



原创粉丝点击