I am working on an app, and at some point the user needs to draw something over an image.
The code i wrote works just fine for images around 1500x1500 and smaller, but once the images get bigger, the problem starts.
When images get too big, it takes more time to do the drawing, and the Gesture Recognizer gets called rarely.
Here’s how I did it: there are two classes, one is a UIScrollView subclass called DrawView and one is a UIImageView subclass called MyPen. DrawView has a UIPanGestureRecognizer that sends messages to MyPen every time it gets recognized (I get the [recognizer state] and depending on it i start or move a line). DrawView has two UIImageView objects in its subviews, one for the background image, and one for the drawings (the pen).
here’s what I do in MyPen:
- (void)beginLine:(CGPoint) currentPoint
{
previousPoint = currentPoint;
}
- (void)moveLine:(CGPoint) currentPoint
{
self.image = [self drawLineFromPoint:previousPoint toPoint:currentPoint image:self.image];
previousPoint = currentPoint;
}
- (UIImage *)drawLineFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint image:(UIImage *)image
{
CGSize screenSize = self.frame.size;
UIGraphicsBeginImageContext(screenSize);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0, 0, screenSize.width, screenSize.height)];
CGContextSetLineCap(currentContext, kCGLineCapRound);
CGContextSetLineWidth(currentContext, _thickness);
CGContextSetStrokeColorWithColor(currentContext, _color);
CGContextBeginPath(currentContext);
CGContextMoveToPoint(currentContext, fromPoint.x, fromPoint.y);
CGContextAddLineToPoint(currentContext, toPoint.x, toPoint.y);
CGContextStrokePath(currentContext);
UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return ret;
}
When the image is big enough, it takes some time for CoreGraphics to render it, and so the gesture recognizer doesn’t get recognized so often, and sends less points to the pen.
The question here is: Is there a way to optimize the drawing? Should I use another Thread for ir ? Is there another way around it ?
Any help greatly appreciated.
You should split foreground (the lines) and the background (the image the lines should be drawn on) into two Views. So you can only update the foreground View every time the user moves his finger. You can compose the two views into one Image when the user finishs drawing.
Drawing an image inside a CGContext is very expensive, especialy when large.