如何使用 UIBezierPath 裁剪图像?
Posted
技术标签:
【中文标题】如何使用 UIBezierPath 裁剪图像?【英文标题】:How to crop the image using UIBezierPath? 【发布时间】:2012-10-31 07:33:12 【问题描述】:我想从UIBezierpath
封闭路径中获取图像(见图)。我使用drawRect
方法在UIView
上绘制图像,并使用drawRect
方法绘制线条。
如何获得特定的封闭路径图像?请帮我。提前致谢。
此代码用于绘制贝塞尔路径。
UIBezierPath *aPath = [UIBezierPath bezierPath];
for (NSString *pointString in pointArray)
if ([pointArray indexOfObject:pointString] == 0)
[aPath moveToPoint:CGPointFromString(pointString)];
else
[aPath addLineToPoint:CGPointFromString(pointString)];
[aPath closePath];
【问题讨论】:
我们如何在 UIImageView 上画一条线,当我尝试在 UIview 上画一条线时,UIview 工作但在 uiimageview 不工作,你能帮我吗 你的目标实现了吗? 嗨,你能回答你自己的问题吗.... @Rajneesh071 Yup. 如果您找到了解决方案,请告诉我。我也在使用类似的功能。 ***.com/questions/30643161/crop-image-in-swift 【参考方案1】:您可以为此使用shapeLayer
。类似的,
UIBezierPath *aPath = [UIBezierPath bezierPath];
for (NSString *pointString in pointArray)
if ([pointArray indexOfObject:pointString] == 0)
[aPath moveToPoint:CGPointFromString(pointString)];
else
[aPath addLineToPoint:CGPointFromString(pointString)];
[aPath closePath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = aPath.CGPath;
[view.layer setMask:shapeLayer];//or make it as [imageview.layer setMask:shapeLayer];
//and add imageView as subview of whichever view you want. draw the original image
//on the imageview in that case
要将其作为图像获取,
UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
image
应该有对应的图片。
【讨论】:
谢谢 ACB...如何从 UIBezierpath 获取图像。 谢谢...我试过了,它得到的图像和背景是白色的。我只想要 UIBezierPath 部分的图像(参见图像猫头)。你懂我吗? 为什么不尝试在 UIImageView 中设置原始图像并使用上面的代码。检查这是否给出了正确的图像。而不是代码中的“视图”使用“图像视图”。 我的问题是在裁剪图像之后,然后转换为黑白图像。图像剩余背景为黑色。所以我正在搜索图像的特定路径。 @ACB 你能把你的代码示例发给我吗,因为我们没有得到正确的图像【参考方案2】:对于 Swift 试试这个:ZImageCropper
ZImageCropper 使用以下内容作为核心部分:
UIBezierPath UITouch 事件 CAShapeLayer CoreGraphics【讨论】:
【参考方案3】:嗯,有几件事你必须注意。
-
您是否传递了 UIImageView 而不是 UIView?
如果是,您是否为触摸处理启用了图像视图?
继承您的 UIImageView 并使用
drawrect()
为您处理这些内容。
如果您只想要图像的一部分(如猫),则需要根据 UIBezierPath 对图像进行子掩码。
更新
以下是一个完整的工作示例,请根据您的要求进行更改。
ViewController.h:
@interface ViewController : UIViewController
UIBezierPath *aPath;
@property (nonatomic,retain) NSMutableArray *pathArray;
@property (nonatomic,retain) NSMutableDictionary *dic;
@property (nonatomic,retain) IBOutlet UIImageView *imgView;
@end
ViewController.m:
@interface ViewController ()
- (IBAction)Crop:(id)sender;
@end
@implementation ViewController
@synthesize pathArray,dic,imgView;
- (void)viewDidLoad
[super viewDidLoad];
- (void) setClippingPath:(UIBezierPath *)clippingPath : (UIImageView *)imgView;
NSLog(@"Mask Paths %@",clippingPath);
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.imgView.frame;
maskLayer.path = [clippingPath CGPath];
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
self.imgView.layer.mask = maskLayer;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
self->aPath = [[UIBezierPath alloc]init];
[aPath moveToPoint:[mytouch locationInView:imgView]];
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
[aPath addLineToPoint:[mytouch locationInView:imgView
]];
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- (IBAction)Crop:(id)sender
[self setClippingPath:aPath :imgView];
【讨论】:
嗨,现在我们如何将此图层保存为背景清晰的uiimage?如***.com/questions/3454356/… 中所述,我尝试将 CALayer self.imgView.layer.mask 转换为 UIImage。但这不是我们想要的结果。 嗨,苏菲扬。我如何开始理解 uibezierpath?我试图阅读文档,但由于我只是一个新手,我发现很难掌握。请指导我一些好的 uibezierpath 教程。谢谢。 有点晚了,但你应该在某个地方渲染你的图层并获得所需的 UIImage..【参考方案4】:使用这个吊舱ios-helpers
- (UIImage *)imageWithStrokeColor: (UIColor *)stroke_color andFillColor: (UIColor *)fill_color
// adjust bounds to account for extra space needed for lineWidth
CGFloat width = self.bounds.size.width + self.lineWidth * 2;
CGFloat height = self.bounds.size.height + self.lineWidth * 2;
CGRect bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, width, height);
// create a view to draw the path in
UIView *view = [[UIView alloc] initWithFrame:bounds];
// begin graphics context for drawing
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);
// configure the view to render in the graphics context
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
// get reference to the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
// reverse the y-axis to match the opengl coordinate space
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -view.bounds.size.height);
// translate matrix so that path will be centered in bounds
CGContextTranslateCTM(context, -(bounds.origin.x - self.lineWidth), -(bounds.origin.y - self.lineWidth));
// stroke color
[stroke_color setStroke];
[self stroke];
//fill color
[fill_color setFill];
[self fill];
// get an image of the graphics context
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
// end the context
UIGraphicsEndImageContext();
return viewImage;
【讨论】:
您能否在答案中添加更多细节?很高兴您包含指向文档和示例代码的链接,但您能描述一下它的具体作用吗?【参考方案5】:如果您在代码中绘制所有内容,只需使用 -addClip
,即:
UIBezierPath *aPath = [UIBezierPath bezierPath];
for (NSString *pointString in pointArray)
if ([pointArray indexOfObject:pointString] == 0)
[aPath moveToPoint:CGPointFromString(pointString)];
else
[aPath addLineToPoint:CGPointFromString(pointString)];
[aPath closePath];
CGContextSaveGState(context);
[aPath addClip];
// draw image
[aPath stroke];
CGContextRestoreGState(context);
【讨论】:
您好 hypercrypt...谢谢您的回复。 如何从特定的 UIBezierPath 获取图像。 创建图像上下文并使用UIGraphicsGetImageFromCurrentImageContext()
谢谢。我想要图像的特定部分(参见图像猫头)。【参考方案6】:
iDev 的回答很好,但是如果你需要透明背景,那么除了
UIGraphicsBeginImageContext(view.bounds.size);
你应该使用
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0);
默认情况下,图像上下文是使用 opaque == YES 创建的,因此您必须将其更改为 NO。
【讨论】:
【参考方案7】:这对我有用...
UIBezierPath *path = ....//your path
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(nil, frame.size.width, frame.size.height, 8, 4*frame.size.width, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
CGContextAddPath(context, path.CGPath);
CGContextClip(context);
CGContextDrawImage(context, frame, image.CGImage);
[UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
【讨论】:
【参考方案8】:// This Work 100%
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
megView = [[UIImageView alloc]initWithFrame:CGRectMake(lastPoint.x , lastPoint.y , k_POINT_WIDTH , k_POINT_WIDTH )];
//[megView setImage:[UIImage imageNamed:@"b_image22.png"]];
[megView setContentMode:UIViewContentModeScaleToFill];
megView.alpha = 2;
//megView.layer.backgroundColor = [UIColor whiteColor].CGColor;
//megView.layer.cornerRadius = megView.frame.size.width / 2;
megView.clipsToBounds = YES;
[self.main_uiview addSubview:megView];
self.bezierPath = [UIBezierPath bezierPath];
[self.bezierPath moveToPoint:lastPoint];
// Touchmove method
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.main_uiview.frame.size);
[self.bg_imageview.image drawInRect:CGRectMake(0, 0, self.main_uiview.frame.size.width, self.main_uiview.frame.size.height)];
megView.frame = CGRectMake( currentPoint.x - k_POINT_WIDTH/2 , currentPoint.y - k_POINT_WIDTH/2 , k_POINT_WIDTH , k_POINT_WIDTH );
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red,green ,blue, 0.20);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);
self.bg_imageview.image = UIGraphicsGetImageFromCurrentImageContext();
[self.bg_imageview setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
[self.bezierPath addLineToPoint:lastPoint];
// TouchEnd Method
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
[megView removeFromSuperview];
// Image Crop Method
-(UIImage *)croppedImage
UIImage *myImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.bezierPath closePath];
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 0.0);
_b_image = self.bg_imageview.image;
CGSize imageSize = _b_image.size;
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, [[UIScreen mainScreen] scale]);
[self.bezierPath addClip];
[_b_image drawInRect:imageRect];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
【讨论】:
以上是关于如何使用 UIBezierPath 裁剪图像?的主要内容,如果未能解决你的问题,请参考以下文章