I want to get the image from the UIBezierpath
closed path(See the image). I draw the image on the UIView
using drawRect
method and als
You can use a shapeLayer
for that. Something like,
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
To get it as an image,
UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
image
should have the corresponding image.
If you're drawing everything in code just use -addClip
, i.e.:
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);
this works for me...
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)];
iDev's answer is excellent, but if you need transparent background, then except
UIGraphicsBeginImageContext(view.bounds.size);
you should use
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1.0);
By default image context is created with opaque == YES, so you have to change it to NO.
// 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;
}
Well, there are a couple of things that you have to take in notice.
drawrect()
for handling that stuff for you.If you want only a portion of the image (like the cat), then you need to submask your image according to UIBezierPath.
Updated
The following is a complete working example, change it to your requirements.
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];
}