我确信已经从不同的角度多次询问过这个问题,但我现在还没有找到答案。
我想要实现的目标 我想要做的是显示UIImage,并允许用户在图像上绘制一个矩形,并最终裁剪他们的选择。
到目前为止的研究 我在这里找到了关于处理裁剪的SO的先前问题,但是它们经常处理不会改变的静态裁剪区域,这确实导致了这种机制的以下约束
通过上述两个变量的组合,几乎不可能准确地预测图像中感兴趣的区域的位置,因此我依靠用户通过能够“绘制”一个方框来定义它我们感兴趣的区域,在这种情况下,是一个路标。
这在Android上都是很好的,因为你可以用一个好的意图委托所有的努力工作,例如:
Intent intent = new Intent("com.android.camera.action.CROP");
但是,我找不到iOS的等价物。
我从source发现了这段代码:
- (UIImage *)imageByDrawingCircleOnImage:(UIImage *)image
{
// begin a graphics context of sufficient size
UIGraphicsBeginImageContext(image.size);
// draw original image into the context
[image drawAtPoint:CGPointZero];
// get the context for CoreGraphics
CGContextRef ctx = UIGraphicsGetCurrentContext();
// set stroking color and draw circle
[[UIColor redColor] setStroke];
// make circle rect 5 px from border
CGRect circleRect = CGRectMake(0, 0,
image.size.width,
image.size.height);
circleRect = CGRectInset(circleRect, 5, 5);
// draw circle
CGContextStrokeEllipseInRect(ctx, circleRect);
// make image out of bitmap context
UIImage *retImage = UIGraphicsGetImageFromCurrentImageContext();
// free the context
UIGraphicsEndImageContext();
return retImage;
}
我认为这是一个很好的裁剪起点(但它确实是裁剪圈),它确实依赖于在调用CGRectMake
时预定义要裁剪的区域。
此previous question还详细说明了如何进行实际裁剪。
我假设允许用户绘制矩形,我需要与手势集成吗?
问题: 如何允许用户在图像视图上绘制矩形,以便裁剪该区域?
答案 0 :(得分:2)
您可以尝试BJImageCropper:
一个简单的UIView子类,允许用户裁剪图像。如果你使用它,我很想知道! Twitter:@barrettjacobsen
答案 1 :(得分:0)
这篇文章已有5年历史,但未来的参考资料,这就是我设法完成它的方法。以下代码是Rob's answer和一些图像裁剪的组合
这里使用Xcode 9和Swift 4
为第一个视图控制器添加ImageView和2个按钮,为最后一个视图控制器添加另一个图像视图
将所有视图链接到源文件
查看控制器
import UIKit
extension UIView {
func snapshot(afterScreenUpdates: Bool = false) -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}
extension UIImage {
func crop( rect: CGRect) -> UIImage {
var rect = rect
rect.origin.x*=self.scale
rect.origin.y*=self.scale
rect.size.width*=self.scale
rect.size.height*=self.scale
let imageRef = self.cgImage!.cropping(to: rect)
let image = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return image
}
}
类ViewController:UIViewController {
var rec: CGRect!
var cropImage: UIImage!
@IBOutlet weak var imageView: UIImageView!
private let shapeLayer: CAShapeLayer = {
let _shapeLayer = CAShapeLayer()
_shapeLayer.fillColor = UIColor.clear.cgColor
_shapeLayer.strokeColor = UIColor.green.cgColor
_shapeLayer.lineWidth = 2
return _shapeLayer
}()
private var startPoint: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
imageView.layer.addSublayer(shapeLayer)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
clear()
startPoint = touches.first?.location(in: imageView)
}
func clear() {
imageView.layer.sublayers = nil
imageView.image = UIImage(named: "aa")
imageView.layer.addSublayer(shapeLayer)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let startPoint = startPoint, let touch = touches.first else { return }
let point: CGPoint
if let predictedTouch = event?.predictedTouches(for: touch)?.last {
point = predictedTouch.location(in: imageView)
} else {
point = touch.location(in: imageView)
}
updatePath(from: startPoint, to: point)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let startPoint = startPoint, let touch = touches.first else { return }
let point = touch.location(in: imageView)
updatePath(from: startPoint, to: point)
imageView.image = imageView.snapshot(afterScreenUpdates: true)
shapeLayer.path = nil
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
shapeLayer.path = nil
}
private func updatePath(from startPoint: CGPoint, to point: CGPoint) {
let size = CGSize(width: point.x - startPoint.x, height: point.y - startPoint.y)
rec = CGRect(origin: startPoint, size: size)
shapeLayer.path = UIBezierPath(rect: rec).cgPath
}
@IBAction func btnTapped(_ sender: Any) {
clear()
}
@IBAction func btnCropTapped(_ sender: Any) {
let newRec = CGRect(origin: CGPoint(x: rec.origin.x, y: rec.origin.y), size: rec.size)
cropImage = imageView.image?.crop(rect: newRec)
print(rec)
print(newRec)
self.performSegue(withIdentifier: "toImage", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toImage" {
if let destination = segue.destination as? ImageViewController {
destination.croppedImage = cropImage
}
}
}
}