Hi want to choose colors in a coloring project that I am trying out.
I am new at this so this might be a silly question. I am using buttons to select different colors. But when the button is pressed the only thing that happens is that the last pixel of the line that was drawn changes to the selected color. In the code below the first tag erases the drawing and the second should change to color for the next line that will be drawn...
-(IBAction)buttonClicked:(UIButton *)sender {
switch (sender.tag)
{
case 1: {
drawImage.image = nil;
return;
}
//lastPoint.y -= 0;
break;
case 2: {
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 1.0, 2.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
break;
default:
break;
}
}
The code:
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
does not reallydraw a line since the start of the line CGContextMoveToPoint and the end of the line CGContextAddLineToPoint are the same point.
A couple of points, less code is better:
Eliminate the switch statement by having a target for each button.
Call UIGraphicsGetCurrentContext() once and save it in a var, just for clarity.
Example:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 3.0);
CGContextSetRGBStrokeColor(context, 0.0, 1.0, 2.0, 1.0);
CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);
CGContextAddLineToPoint(context, lastPoint.x, lastPoint.y);
CGContextStrokePath(context);
Related
I use this code to draw a line in quartz2d
CGPoint currentPoint = CGPointMake(rascalImage.center.x, rascalImage.center.y);
currentPoint.y += 10;
UIGraphicsBeginImageContext(self.view.frame.size);
[drawingView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawingView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
Now how would I go about making an erase function for just where the eraser intersects? I know that I have to erase a certain point from the line (where the eraser touches), I just don't know how to do this so please help!!
UIGraphicsBeginImageContext(imgBlankView.frame.size);
[imgBlankView.image drawInRect:CGRectMake(0, 0, imgBlankView.frame.size.width, imgBlankView.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(),lineWidth);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint1.x, lastPoint1.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
imgBlankView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I assume you are not drawing on a solid colored background? If you are, just use the same function to draw background-colored lines over the contrasting lines.
But, since you most likely have a complex background: Once you end the graphics context, and get a UIImage from the lines you have drawn, there is no way to erase just the lines. If you are creating some sort of complex drawing app, I would suggest that you use layers, and simply "stack up" layers one on top of the other to create the drawing environment.
Check out this post also:
How to erase some portion of a UIImageView's image on iOS?
I used below code for free hand drawing on the whole view:
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Now my requirement is something like this .. I should be able to draw on particular area of a view. So I modified the code like this ..
UIGraphicsBeginImageContext(CGSizeMake(300, 100));
[drawImage.image drawInRect:CGRectMake(0, 0, 400, 100)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
but the drawing is not proper. Please suggest me how to do this.
Create custome view like :
UIView *drawingView = [[UIView alloc] initWithFrame:CGRectMake(x, y,
300, 300)];
[self.view addSubView:drawingView];
And Then modify your code something like below :
UIGraphicsBeginImageContext(drawingView.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, drawingView.frame.size.width, drawingView.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
i want to erase image in view (like erase drawing with Eraser).i did if view frame is 0,0,320,480 ,but i worry if the view frame has different size:
here my code:
UIGraphicsBeginImageContext(self.view.frame.size);
[myImageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaNone);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), point.x, point.y);
//this line code for erasing select the part of the image
CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(point.x, point.y, 30, 30));
//End the code
CGContextStrokePath(UIGraphicsGetCurrentContext());
myImageView.image = UIGraphicsGetImageFromCurrentImageContext();
Try the below code ..
UIGraphicsBeginImageContext(self.frame.size);
[imageView.image drawInRect:CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 30.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 1.0, 1.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastTouch.x, lastTouch.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I have the following code but it is not smooth. If I draw a circle, i see the sharp corners.
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), YES);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
You are seeing some of the sharp corners because you are drawing too many short antialiased line segments, which all takes more than 1/60th of a second, thus you end up missing UI touch event updates, which leads to a more jaggy path.
2D CG drawing is not accelerated on iOS devices.
If you want to stick with CG drawing, try drawing only the last 4 or so line segments, maybe turn off antialiasing, and see if that's smoother. Then fill in the rest after the path drawing is done (touch up).
Even with a full 60FPS you'll get edges instead of a curve. Your best bet with CG is to use bezier paths. Outside of CG, splines.
what you need to do is not call the drawing functions every time the touch moves, instead make an accumulator and increment it every time it's called. if it reaches some threshold then you do the drawing code. but you should definitely run it the first time the method is called. to find a good threshold you must experiment with it.
static int accum = 0;
if ((accum == 0) || (accum == threshold)) {
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), YES);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
accum = 0;
}
accum++;
IS it possible to draw line with special shape for example like dotted(China Point) ? i draw line with below code
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, 320, 480)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.867, 0.867, 0.867, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), startPoint.x, startPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), endPoint.x, endPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Maybe CGContextSetLineDash is what you want.
It sets the pattern for dashed lines in a graphics context.
void CGContextSetLineDash (
CGContextRef c,
CGFloat phase,
const CGFloat lengths[],
size_t count
);
This example draws a line with circles (diameter: 20 points, distance: 40 points):
CGContextSetLineWidth(context, 20.0);
CGFloat dash[] = {0.0, 40.0};
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineDash(context, 0.0, dash, 2);
CGContextMoveToPoint(context, 10.0, 30.0);
CGContextAddLineToPoint(context, 310.0, 30.0);
CGContextStrokePath(context);