I've started to learn Objective-c with making drawing app. Many people ask how to make a brush like in Photoshop, so I am posting here my solution.
Step-by-step instruction.
1) You need to store points of the curve that user has drawn by touch (its easy - you need to create NSMutableArray and add CGPoints created with location of touch to it in touchesMoved event)
2) Now lets create brush
This is how we are going to make it:
1) paint image that we are going to use as brush in appropriate color and scale it
2) draw this image along the path we created in 1st part
Create extension of UIImage class
and add following method
+(UIImage*)imageNamed:(NSString *)name withColor:(UIColor*)color Scale:(float)scale
{
UIImage* img=[UIImage imageNamed:name];
UIGraphicsBeginImageContext(img.size);
CGContextRef context=UIGraphicsGetCurrentContext();
[color setFill];
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGRect rect =CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context, kCGPathFill);
UIImage*coloredImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage*ret=[UIImage imageWithCGImage:coloredImage.CGImage scale:1/scale orientation:coloredImage.imageOrientation];
return ret;
}
Now lets draw it
I've made my own classes to store curve and points: drawnCurve and drawnPoint, drawnCurve has NSMutableArray of drawnPoints-drawnCurve.points.
This method is called in drawnCurve class. shouldFar tells if we should draw images far from each other like in spray,or not-like in pencil.
-(void)primitiveDrawAtContext:(CGContextRef)context withBrush:(UIImage*)brush shouldFar:(BOOL)f1
CGFloat hyp;
hyp=sqrtf(brush.size.width*brush.size.width+brush.size.height*brush.size.height);
drawnPoint*beg=[self.points objectAtIndex:0];
CGContextMoveToPoint(context, beg.x, beg.y);
CGPoint t=CGPointMake(beg.x, beg.y);
CGLayerRef layer=CGLayerCreateWithContext(context, CGSizeMake(brush.size.width,brush.size.height), NULL);
CGContextRef tmp=CGLayerGetContext(layer);
CGContextDrawImage(tmp,CGRectMake(0, 0, brush.size.width, brush.size.height), brush.CGImage);
CGContextBeginTransparencyLayer(context, NULL);
CGContextDrawLayerAtPoint(context, CGPointMake(t.x-brush.size.width/2, t.y-brush.size.height/2), layer);
for(int i=0;i<self.points.count-1;i++)
{
drawnPoint* cur=[points objectAtIndex:i];
drawnPoint* next=[points objectAtIndex:i+1];
if(f1)
count=(int)sqrt((cur.x-next.x)*(cur.x-next.x)+(cur.y-next.y)*(cur.y-next.y))/(hyp);
else {
count=(int)sqrt((cur.x-next.x)*(cur.x-next.x)+(cur.y-next.y)*(cur.y-next.y))/(0.25*hyp);
}
double stepX=(next.x-cur.x)/count;
double stepY=(next.y-cur.y)/count;
for(int j=0;j<count+1;j++)
{
CGContextDrawLayerAtPoint(context,CGPointMake(cur.x+j*stepX-brush.size.width/2, (cur.y+j*stepY-brush.size.height/2)) , layer); }
if(f1==YES) {
if((count==0) && (sqrt(pow((cur.x-t.x),2)+pow((cur.y-t.y),2))> max(0.5*hyp,3)))
{
CGContextDrawLayerAtPoint(context, CGPointMake(cur.x-brush.size.width/2, cur.y-brush.size.height/2), layer);
t.x=cur.x;
t.y=cur.y;
}
}
else {
if((count==0) && (sqrt(pow((cur.x-t.x),2)+pow((cur.y-t.y),2))>min(3,0.5*hyp)))
{
CGContextDrawLayerAtPoint(context, CGPointMake(cur.x-brush.size.width/2, cur.y-brush.size.height/2), layer);
t.x=cur.x;
t.y=cur.y;
}
}
}
Here is the result
If you have any questions or you need some code - you are welcome to ask!
Hey, could you maybe post the Xcode project files? This looks really useful, but you don't give much context, and it's hard to understand where these methods go.
ReplyDeleteHi,
ReplyDeleteCan you share project sample please.
Hey Can you please email me your sample project to kapilan1989@gmail.com ? It would be a great help.
ReplyDeleteHi, i m looking for this kind of project from many days...
ReplyDeleteThanks you very much..
Can you please upload xcode project or mail me at jrt814@gmail.com ...
Thanks again!!!
Hello i follow your instruction but when i draw nothing happens...
ReplyDeleteCan you tell me pls which kind of class is drawnCurve?
I made drawnPoint class as nsobject to store cgpoints and it seems to work, but the app doesn't draw.. Pls help me! TY!
Hey Can you please send me your sample project to slavcopetkovski@yahoo.com ?
ReplyDeleteThank you.
Please send me this project at kishimotovn@gmail.com
ReplyDeleteI would be very grateful, tks :D
Please upload project to github or send me to abbadoh@gmail.com
ReplyDeletePlease send me this project at amit.044012@gmail.com
ReplyDeletePlease send me this project at urja.leewayinfotech@gmail.com
ReplyDeletePlease send me this project at hangkimduyen@gmail.com, thank you very much!
ReplyDeleteHello, please send me the source code at lamtran.tech@gmail.com, thank you.
ReplyDeleteHello, please send me the source code at lamtran.tech@gmail.com, thank you.
ReplyDeleteHello, could you please send me a copy of the project at patriciotinoco@gmail.com, thank you in advance :)
ReplyDeletehey..can i get the whole code..beacuse there are some varibles that are not defined here..! please help..ASAP. Thanku
ReplyDeleteP.S.: Mail=> rednimrah20@gmail.com
Hello, please send me the source code at sanjay.jogani.mit@gmail.com, thank you.
ReplyDeleteHi, tks you very much. Can you send me the source code at boy.ice.tea@gmail.com. Tks
ReplyDeleteplease send me the source code at brijesh.gurutechnolabs@gmail.com
ReplyDeleteplease send me the source code: vominhtri1049@gmail.com. Thanks you very much!
ReplyDeletePlease send me source code: oxid_burn@ukr.net.
ReplyDeleteThank you very much!
Please send me the source code sakura20193@gmail.com
ReplyDeleteThank you very much!
Please send me the source code mubassher10@gmail.com
ReplyDeleteThank you very much!
(copy + paste ) => oguzhan.akbudak@hotmail.com.tr ( copy + paste ) :)
ReplyDeleteThis comment has been removed by the author.
ReplyDeletePlease send me the source code gizingun@gmail.com
ReplyDeleteThank you very much!
Hi,please send me the source code at felixkongmr@gmail.com
ReplyDelete