I was going through how to use UIBezierPath and what are its possible uses.. and I must say it is one hell of a convenient tool ! Ofcourse you can draw normal drawing with it as shown below and use your app as sketching pad in addition to that it adds so much convenience with the undo and redo action(will write that tutorial too next) that I fell in love with the use of UIBezierPath. You can have simple drawing as well as pattern based brush tip. It is sooo easy to use this as pencil too that I don't even have words !
You can init the UIBezierPath as following
UIBezierPath *myPath=[[UIBezierPath alloc]init];
myPath.lineWidth=10;
brushPattern=[UIColor redColor]; //This is the color of my stroke
Then you have Touch methods which handle and track the coordinates of your touch. When your touch begins on the screen, you ask UIBezierPath to move to that touch point
UITouch *mytouch=[[touches allObjects] objectAtInd
[myPath moveToPoint:[mytouch locationInView:self]];
As you move your finger around, you keep adding those points in your BezierPath in TouchMoved method by following
UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
[myPath addLineToPoint:[mytouch locationInView:self]];
As we need constant refreshing of the screen, so that as soon as we draw it appears on the screen, we refresh the UIView subclass by calling following method in TouchMethod so that as soon as there any change in the BezierPath, it is reflected on the screen.
[self setNeedsDisplay];
Talking about drawRect Method which does all the drawing for you, you need to set the color of your stroke(stroke color means the color with which painting will be done on screen.) on screen and also the blend mode. You can try different blend mode and see the result.
- (void)drawRect:(CGRect)rect
{
[brushPattern setStroke];
[myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
Pattern brush.. doesn't exactly work the way it is in Photoshop , because once you fill the whole screen with your drawing, the screen looks completely like a screen full of tiles of your pattern which is not what I would want but ... thats what we have so far in terms of pattern brush. I am trying to implement the brush with opengl lets see if I succeed then I will post it here !
myPath.lineWidth=10;//This can help you in setting width of your stroke/brush
brushPattern=[[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"pattern.jpg"]]; //You can set pattern in your color of your brush so that the strokes will appear with pattern of your image.
You can download the code HERE
Update:
Thanks to Sonia for pointing it out , wanted to know about smoothing of edges of bezier path, so that it doesn't look distorted . You can change the capStyle of line for that. I have changed it and updated the code at above link.
Well.. Finally implemented and uploaded code implementing Undo-Redo.
POSTED HERE
Thanks for the tutorial. But, how can we implement the undo? Any update for this?
ReplyDeleteI have posted an article about how to implement undo-redo in BezierPath
ReplyDeletehttp://soulwithmobiletechnology.blogspot.com/2011/06/redo-undo-in-paint-feature.html
Reetu, I am having a devil of a time merging the undo/redo code with the line drawing code. The difficulty is that I have segmented controls for brushes, colors and background pictures. I have posted a question on StackOverflow here: http://stackoverflow.com/questions/10142404/xcode-undo-a-bezier-path, but no answers so far. Would you be willing to have a look at the offending methods? I would really appreciate that.
DeleteDavid
great tutorial.
ReplyDeleteis there a straightforward way to add an image to the MyLineDrawingView background to draw "over". ?
This comment has been removed by the author.
ReplyDeleteHi reetu, hope u are fine...great tutorial once again.I only want to draw straight lines, start it when the user double tap on the screen & end it when the user again double tap on the screen.How can do it with UIBezierPath?
ReplyDeleteNice drawing app!
ReplyDeleteAnd
REETU RAJ nice redoo undo
I have been searching for this technique for some time. It sure is better than the Apple GLPaint sample. Thank you so much for figuring this out and making it available. You are very generous.
ReplyDeleteDavid
One thing...Reetu, how would I save the screen - either as a file or a screenshot?
ReplyDeleteThanks!!
I will post the little code snippet for that.
ReplyDeleteThanks. That would be wonderful...
DeleteHi Reeta, I got this code to work - it saves the image to the photo album. Maybe other can use it - probably, you can improve it.. David
Deleteps. The flash screen method is cool. It signals that the save worked...
- (IBAction)saveButtonTapped:(id)sender
{
NSLog(@"%s", __FUNCTION__);
[self captureToPhotoAlbum];
[self flashScreen];
}
-(void)captureToPhotoAlbum {
NSLog(@"%s", __FUNCTION__);
// UIImageWriteToSavedPhotosAlbum(drawImage.image, self, nil, nil);
//return;
// Get image to save
CGImageRef screen = UIGetScreenImage();
UIImage *img = [UIImage imageWithCGImage:screen];
// Image cropping
CGImageRef imageRef = CGImageCreateWithImageInRect([img CGImage], CGRectMake(0.0f, 70.0f, 768.0f, 768.0f));
UIImage *img2Save = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// Request to save the image to camera roll
UIImageWriteToSavedPhotosAlbum(img2Save, self, nil, nil);
}
-(void) flashScreen {
NSLog(@"%s", __FUNCTION__);
UIWindow* wnd = [UIApplication sharedApplication].keyWindow;
UIView* v = [[UIView alloc] initWithFrame: CGRectMake(0, 0, wnd.frame.size.width, wnd.frame.size.height)];
[wnd addSubview: v];
v.backgroundColor = [UIColor whiteColor];
[UIView beginAnimations: nil context: nil];
[UIView setAnimationDuration: 1.0];
v.alpha = 0.0f;
[UIView commitAnimations];
}
Thank you mam for your code.
ReplyDeleteMam I am developing a book app in ipad where user can write notes. For that i need a pen like structure through which user can make note and save it and will see it again when he came to same page or where ever i list him notes. So how to implement them and save them so that user can see his notes same as he wrote. I never work on drawing before in iphone/ipad. I will be obliged for any guidance and help.
Hello mam,
ReplyDeleteMam I want to create a notebook like app like bamboo app, neu notepad etc
I have started reading coregraphics for that
But not getting right approach what should be read and from where.
because in my previous app I just started working on it without knowing cons and prons of the library i used and hence results into disaster. This time i dont want to repeat that. An app in which one can write, draw , erase, color change etc. (the functionality required by a notebook.)
Can you suggest me some tutorial or site from where I can read and able to develop such App by my own
Thank you in advance
@Sonia, You can easily use UIBezierPath for all the needs you mentioned above - write/draw/erase/color change of pen.
ReplyDeleteThis is just an introductory tutorial, you can read more about it on Apple's website. to learn more deeply about it.
I think you have just started in this application.
I wish you best of luck, I am sure this reply is good enough to guide you in the right direction.
I just wanted to confirm is bezier curve is enough for writing and sketching so that i can proceed in that. From your reply i got it. As with the code you provided not able to draw smoothly and not able to put simple dots so i was little bit confused but now I started working on it.
ReplyDeleteThank You mam for your reply.
Thanks for your nice tutorial.
ReplyDeleteI integrate it in my app but in my app there is extra feature i.e. to erase the path which we draw using an eraser.
User has an option to change the size of eraser.
I googled it & fount the solution that use pattern image similar to the background but I dont want this.
If you have any option the please help me.
Thanks.
@Sonia, you can change the capStyle, I have changed it and updated the code on the link to download.
ReplyDelete@Giri, you can use the Basic draw line method with CGContext and changing to BlendMode of CGContext to Clear.
I tried it using following code -
ReplyDeleteCGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeClear);
CGContextBeginTransparencyLayer(ctx, NULL);
{
CGContextSetGrayFillColor(ctx, 0.0, 1.0); // solid black
CGContextAddPath(ctx, pathToErase);
CGContextFillPath(ctx);
// the above two lines could instead be CGContextDrawImage()
// or whatever else you're using to clear
}
CGContextEndTransparencyLayer(ctx);
it draws he line but with black color.
I googled lots with no luck.
If you have possible then please share some amount of code with me.
Thank you very much for this. It was a great starting point. Is there anyway to validate the drawing?
ReplyDeleteFor example, lets say there are dots on the screen and we use your code to draw the line. Any way to check the final drawn image is correct?
Thanks.
Hello Reetu, thanks for your post, it helped me a lot, but now I am trying to draw different color lines by selecting color options, below is my code, which I tried so far
ReplyDelete- (void)drawRect:(CGRect)rect
{
if(changecolor)
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
strokeColor = appDelegate.color;
NSLog(@"%@",strokeColor);
SEL blackSel = NSSelectorFromString(strokeColor);
UIColor* tColor = nil;
if ([UIColor respondsToSelector: blackSel])
tColor = [UIColor performSelector:blackSel];
[tColor setStroke];
[tColor setFill];
for (UIBezierPath *_path in pathArray)
{
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
}
else
{
[[UIColor redColor] setStroke];
[[UIColor redColor] setFill];
for (UIBezierPath *_path in pathArray)
{
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
}
But what is happening here is , if I first draw a red line and later by selecting color options , I try to draw a blue line, my previous red line also becomes blue, I know that because I am using the same array, its turning blue, but how to slove this issue, whether I should use different arrays, but that will not be a optimal solution. so I need your help. waiting for your reply
Hi Ranjit,
ReplyDeleteEverytime you add a line on your screeen, it gets added to pathArray as a bezier path.As you can see in for(UIBezierPath *_path in pathArray), it runs loop on all those lines here without setting stroke color [[UIColor redColor] setStroke];. If you want to make different bezier paths of differnt color, you will have to keep a color array too. Or Another wise way way will be to make a custom class(say MyColoredBezier) with 2 members UIBezierPath and UIColor, then everytime you add a new line or new color, a new object of MyColoredBezier is created, later on you run the loop with setStroke & strokeWithBlendMode as for (MyColoredBezier *obj in coloredpathArray). Hope this answers your query.
for (MyColoredBezier *obj in coloredpathArray)
{
[obj.color setStroke];
[obj.path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
Could you help a beginner in the community and tell me how did you implemented this? How did you wrote the m file of MyColoredBezier and then implemented the change of colors?
DeleteThanks Reetu, I will try it and get back to you.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi reetu, thanks for your suggestion, It works perfectly, I had one more doubt, how to erase a part of line drawn and not the whole line?
DeleteHI.....Reetu
ReplyDeleteI'd like to find a way to be able to draw on UIImageView AND ZOOM on it
and draw.
It is weird because I don't have idea to implement this. Why I say weird is because I manage to create a zoom system for UIImageView, using the UIScrollView. But how to be able to do the drawing on the imageview after zooming in? because when you touch and move your finger on the image to draw, then it becomes to pan function for the image. Or, if I put a button to toggle between Pan & draw, would that be acceptable to you (as user point of view)?
can u help me out?
Hi reetu, I am following your approach for a drawing project, everything works fine, but as we are using an array to store bezeirpaths, after some drawing, their is a lag in the line drawn, I have implemented an erase function, if I erase the line I draw and then again I try to draw a line, I get serious performance issues, I googled about this issue, and the solution is to use CGLayers, Can you throw some light on this? It would be very helpful for me. I am confused on how to use CgLayers.
ReplyDeleteFor me the first line between the first two points is a straight line but then after that it is nice and curved. Is there a way to make it curved between the first two points as well?
ReplyDeleteOn drawing continuously without lifting your finger up, drawing becomes very very slow. And it also increases the memory allocation. What is the solution to that?
ReplyDeleteThe overseas designer for the devoted iPhone development
ReplyDeleteshould be able to provide you the appropriate programs with the highest skills with the extremely innovative technological innovation like Cocoa/Objective C as well as Xcode / Interface Designer with excellent skills, which can be possible when they have excellent encounter and information in this technological innovation.
At first i would say Thank you for this great tutorial. But how can i add a single Point on the screen.
ReplyDeleteThe case is made of flexible thermoplastic material that is agile and elastic, suitable to protect your iPhone 4 Parts without adding to its weight or size...
ReplyDeleteThanks for sharing...!!!!
There is a lot of competition in outsourcing software development, as there are many firms across the globe catering to clients looking for outsourcing their work. What is good is that the takers can choose the best from the lot.
ReplyDeleteCado Magenge
"http://appdevelopmentcompany.com.au/android-application-development.html"
"http://www.appdevelopmentcompany.com.au/email-marketing.html"
"http://appdevelopmentcompany.com.au/iphone-application-development.html"
”http://appdevelopmentcompany.com.au/ipad-application-development.html”
Whatsapp Number Call us Now! 01537587949
ReplyDeleteplease visit us: Seo service
sex video: phone home buttons repair Canton
pone video usa: Mobile Phone Repair
pone video usa: Courier Companies In USA