裁剪图像包含在 4 边(非矩形)多边形中
Posted
技术标签:
【中文标题】裁剪图像包含在 4 边(非矩形)多边形中【英文标题】:Crop image enclosed in a 4 sided (not rectangle) polygon 【发布时间】:2016-02-24 17:24:50 【问题描述】:如何裁剪包含在随机多边形(4 边而非矩形)内的图像部分。只是想知道要遵循哪种方法而不是代码。
【问题讨论】:
对多边形视图进行快照。 获取与该四边形等效的CGRect
:“包含”多边形的最小矩形。然后裁剪。找到CGRect
的方法是您的问题吗?您还可以将多边形区域之外的图像部分设置为透明。
@Teja Nandamuri:我想裁剪多边形内的区域。多边形可以动态改变其尺寸
@Larme:通过选择最小矩形,我不会得到包含在多边形中的精确图像
之后必须敷面膜!你的多边形是如何创建的?
【参考方案1】:
您可以在 Core Graphics 中轻松做到这一点。
您只需要创建一个新的图像上下文,将路径添加到上下文,然后将上下文裁剪到路径。然后,您可以在其中绘制图像并得到裁剪的图像。
-(UIImage*) cropImage:(UIImage*)image withPath:(UIBezierPath*)path // where the UIBezierPath is defined in the UIKit coordinate system (0,0) is top left
CGRect r = CGPathGetBoundingBox(path.CGPath); // the rect to draw our image in (minimum rect that the path occupies).
UIGraphicsBeginImageContextWithOptions(r.size, NO, image.scale); // begin image context, with transparency & the scale of the image.
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -r.origin.x, -r.origin.y); // translate context so that when we add the path, it starts at (0,0).
CGContextAddPath(ctx, path.CGPath); // add path.
CGContextClip(ctx); // clip any future drawing to the path region.
[image drawInRect:(CGRect)CGPointZero, image.size]; // draw image
UIImage* i = UIGraphicsGetImageFromCurrentImageContext(); // get image from context
UIGraphicsEndImageContext(); // clean up and finish context
return i; // return image
例如,如果我们截取您的问题的屏幕截图(我找不到任何其他图片在说谎!)
并使用以下代码....
UIImage* i = [UIImage imageNamed:@"3.png"];
UIBezierPath* p = [UIBezierPath bezierPath];
[p moveToPoint:CGPointMake(0, 0)];
[p addLineToPoint:CGPointMake(1500, 500)];
[p addLineToPoint:CGPointMake(500, 1200)];
UIImage* i1 = [self cropImage:i withPath:p];
这将是输出...
如果您要定期裁剪图像,您甚至可以将其添加到 UIImage
类别中。
【讨论】:
我已经使用了代码,但它没有给出我用 UIBezeir 路径选择的区域,而是在裁剪后给出了一些其他区域。需要帮助 @aman 我怀疑你试图在 UIKit 坐标系中指定你的路径((0,0)
在左上角)。我的答案旨在在图像坐标系中工作((0,0)
位于左下角)。我已经修改了它以在 UIKit 坐标系中工作,所以它现在应该适合你了。
swift 版本好吗?
@DeyaEldeen 您无法将哪个部分转换为 Swift?由于问题被标记为objective-c
,我不想用 Swift 版本混淆我的答案 - 但转换应该相当简单。 Core Graphics 函数调用保持不变,只需将变量声明中的类型更改为let
,将drawInRect:
调用替换为image.drawInRect(...)
,并将方法签名替换为等效的Swift (func cropImage(image:UIImage, withPath:UIBezierPath) -> UIImage ...
)。跨度>
@originaluser2:感谢您的所有帮助,我已经使用了您的新代码。我仍然面临一个问题。我正在使用 JBCroppableView 来选择图像的随机区域。我正在尝试使用所选区域的 UIBezeir 路径来裁剪图像(JBCroppableView 仅掩盖额外区域)。但裁剪后的图像并不完全是我选择的区域。它还裁剪了一些调整非选定区域。裁剪的区域也接近所选区域的 1/4。我已经尝试了一切,但我不知道我错过了什么。【参考方案2】:
为 Swift 3 更新。
我注意到那里的许多实现似乎都希望背景为白色或透明,而我真的只希望背景颜色为黑色。
extension UIImage
func crop(withPath: UIBezierPath, andColor: UIColor) -> UIImage
let r: CGRect = withPath.cgPath.boundingBox
UIGraphicsBeginImageContextWithOptions(r.size, false, self.scale)
if let context = UIGraphicsGetCurrentContext()
let rect = CGRect(origin: .zero, size: size)
context.setFillColor(andColor.cgColor)
context.fill(rect)
context.translateBy(x: -r.origin.x, y: -r.origin.y)
context.addPath(withPath.cgPath)
context.clip()
draw(in: CGRect(origin: .zero, size: size))
guard let image = UIGraphicsGetImageFromCurrentImageContext() else
return UIImage()
UIGraphicsEndImageContext()
return image
【讨论】:
以上是关于裁剪图像包含在 4 边(非矩形)多边形中的主要内容,如果未能解决你的问题,请参考以下文章