How to draw lines in iOS platform - ios

I am using apps like bamboo book and paper, in iPad, the experience is really good, how is it work? which technology does it used when draw lines or curves on screen?

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
//self.imageView.image = nil;
return;
}
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
CGFloat components[3];
[self getRGBComponents:components forColor:self.colorView.backgroundColor];
NSLog(#"%f %f %f", components[0], components[1], components[2]);
UIGraphicsBeginImageContext(self.view.frame.size);
[self.imageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), components[0], components[1], components[2],5.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
//self.imageView.image = nil;
return;
}
if(!mouseSwiped) {
CGFloat components[3];
[self getRGBComponents:components forColor:self.colorView.backgroundColor];
NSLog(#"%f %f %f", components[0], components[1], components[2]);
UIGraphicsBeginImageContext(self.view.frame.size);
[self.imageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), components[0], components[1], components[2], 5.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
Also check following link
http://www.techotopia.com/index.php/An_iOS_4_iPhone_Graphics_Drawing_Tutorial_using_Quartz_2D
https://stackoverflow.com/questions/6449661/drawing-2d-images-on-iphone-tutorials
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_freehand-drawing/
http://www.raywenderlich.com/18840/how-to-make-a-simple-drawing-app-with-uikit

Related

iOS: Problem with my drawing popover that doesn't display well since iOS13

I display a popover that's allows to draw inside.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
NSLog(#"lastPoint: %#", NSStringFromCGPoint(lastPoint));
UIGraphicsBeginImageContext(self.view.frame.size);
[mainImage.image drawInRect:CGRectMake(0, 0, 600, 400)];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
[mainImage setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}
My problem is that since the iOS13, it doesn't display well.
How it should display:
How it display now in iOS13:
Any ideas?

Draw line on image by handgetsture in objective c

I have set image's content mode aspect fit.
Now issue is that, when I'm drawing line on image, that time image's content mode set scaletofill and my image stretched. So I want solution for when I'm drawing line on image, image content mode remain same.
U can download myproject from this link.
I'm using following code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(self.tempImage.image==nil)
{
return;
}
colorPicker.hidden = YES;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
_pointsArray = [NSMutableArray array];
[_pointsArray addObject:NSStringFromCGPoint(lastPoint)];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.tempImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, brush);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, lastPoint.x, lastPoint.y);
CGContextStrokePath(context);
self.tempImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self setupExternalScreen];
UIGraphicsEndImageContext();
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.tempImage.image==nil)
{
return;
}
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
//Now set our brush size and opacity and brush stroke color:
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, brush);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor);
CGContextSetBlendMode(context,kCGBlendModeNormal);
CGContextStrokePath(context);
self.tempImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempImage setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
[self setupExternalScreen];
[self.pointsArray addObject:NSStringFromCGPoint(lastPoint)];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.tempImage.image==nil)
{
return;
}
//handle single tap, make _pointsArray has two identical points, draw a line between them
if (_pointsArray.count == 1) {
[_pointsArray addObject:NSStringFromCGPoint(lastPoint)];
}
[self.stack addObject:_pointsArray];
NSLog(#"color -> %# \nwidth->%f", self.selectedColor.description, brush);
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:self.selectedColor forKey:#"color"];
[dic setObject:[NSNumber numberWithFloat:brush] forKey:#"width"];
[self.contextArray addObject:dic];
[self setupExternalScreen];
[self.undoManager registerUndoWithTarget: self
selector: #selector(popDrawing)
object: nil];
}
In this code, view frame set in UIGraphicsBeginImageContext. I think it will possible using subclass of UIImageView. I don't know exact solution.
Please see this Screenshot, u will easily understand my problem
Thanks in advance

Generate image that was drawn

In my xcode project, the user draws an object manually. So for example they can draw a apple or triangle.
I need to save I guess the coordinates or the line path of what they draw.
How can I store the line path or re-create the image that the user has drawn. I don't want to save the image, but I want to learn from the image the user drew by knowing the specific line path?
Here is the code
.h
int mouseMoved;
BOOL mouseSwiped;
CGPoint lastPoint;
UIImageView *drawImage;
viewdidload {
drawImage = [[UIImageView alloc] initWithImage:nil];
drawImage.frame = self.view.frame;
[self.view addSubview:drawImage];
self.view.backgroundColor = [UIColor lightGrayColor];
mouseMoved = 0;
}
.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
BOOL mouseSwiped = NO;
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
drawImage.image = nil;
return;
}
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
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();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
drawImage.image = nil;
return;
}
_startPoint = [touch locationInView:self.view];
if(!mouseSwiped) {
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);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
-(void)digitalSignatureCalled{
//viewSign.backgroundColor = [UIColor lightGrayColor];
//create a frame for our signature capture based on whats remaining
imageFrame = CGRectMake(0, 50, 500, 450);
//allocate an image view and add to the main view
mySignatureImage = [[UIImageView alloc] initWithImage:nil];
mySignatureImage.frame = imageFrame;
mySignatureImage.backgroundColor = [UIColor whiteColor];
[viewSign addSubview:mySignatureImage];
}
//when one or more fingers touch down in a view or window
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//did our finger moved yet?
fingerMoved = NO;
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//we need 3 points of contact to make our signature smooth using quadratic bezier curve
currentPoint = [touch locationInView:mySignatureImage];
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
lastContactPoint2 = [touch previousLocationInView:mySignatureImage];
}
//when one or more fingers associated with an event move within a view or window
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//well its obvious that our finger moved on the screen
fingerMoved = YES;
UITouch *touch = [touches anyObject];
//save previous contact locations
lastContactPoint2 = lastContactPoint1;
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
//save current location
currentPoint = [touch locationInView:mySignatureImage];
//find mid points to be used for quadratic bezier curve
CGPoint midPoint1 = [self midPoint:lastContactPoint1 withPoint:lastContactPoint2];
CGPoint midPoint2 = [self midPoint:currentPoint withPoint:lastContactPoint1];
//create a bitmap-based graphics context and makes it the current context
UIGraphicsBeginImageContext(imageFrame.size);
//draw the entire image in the specified rectangle frame
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
//set line cap, width, stroke color and begin path
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
//begin a new new subpath at this point
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), midPoint1.x, midPoint1.y);
//create quadratic Bézier curve from the current point using a control point and an end point
CGContextAddQuadCurveToPoint(UIGraphicsGetCurrentContext(),
lastContactPoint1.x, lastContactPoint1.y, midPoint2.x, midPoint2.y);
//set the miter limit for the joins of connected lines in a graphics context
CGContextSetMiterLimit(UIGraphicsGetCurrentContext(), 2.0);
//paint a line along the current path
CGContextStrokePath(UIGraphicsGetCurrentContext());
//set the image based on the contents of the current bitmap-based graphics context
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
//remove the current bitmap-based graphics context from the top of the stack
UIGraphicsEndImageContext();
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//if the finger never moved draw a point
if(!fingerMoved) {
UIGraphicsBeginImageContext(imageFrame.size);
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
//calculate midpoint between two points
- (CGPoint) midPoint:(CGPoint )p0 withPoint: (CGPoint) p1 {
return (CGPoint) {
(p0.x + p1.x) / 2.0,
(p0.y + p1.y) / 2.0
};
}
-(void)clickToSave:(id)sender{
//convert image into .png format.
viewNewSign.image = mySignatureImage.image;
if (mySignatureImage.image == nil) {
imgString = #"NoSignature";
}else{
imgString = [self getStringFromImage:mySignatureImage.image];
}
NSLog(#"image saved = %#",imgString);
NSLog(#"image length = %lu",(unsigned long)imgString.length);
viewSign.hidden = TRUE;
scroll.scrollEnabled = YES;
[scroll bringSubviewToFront:viewSign];
}
-(NSString *)getStringFromImage:(UIImage *)image{
if(image){
NSData *dataObj = UIImagePNGRepresentation(image);
//[appDelegate showAlert:#"Data Size" message:[NSString stringWithFormat:#"Data length = %lu",(unsigned long)dataObj.length]];
return [dataObj base64EncodedStringWithOptions:0];
} else {
return #"";
}
}
-(void)clickToClear:(id)sender{
[self digitalSignatureCalled];
}
- (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Implementing NSUndoManager with Paint Application

I am new to iOS and building a paint application.
Everything goes ok..but I am unable to implement NSUndoManager in my application for undo and redo purpose.
The problem is that I am unable to store the previous state of painting for undo.
Here is the code
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.tempDrawImage];
[[self.undoManage prepareWithInvocationTarget:self]
touchesMoved:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.tempDrawImage];
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width,
self.view.frame.size.height)];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIGraphicsBeginImageContext(self.tempDrawImage.frame.size);
[self.tempDrawImage.image drawInRect:
CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)
blendMode:kCGBlendModeNormal alpha:1.0];
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[[self.undoManage prepareWithInvocationTarget:self] touchesMoved:touches
withEvent:event];
UIGraphicsEndImageContext();
}
-(void)undo
{
[self.undoManage undo];
}
-(void)redo
{
[self.undoManage redo];
}

drawing application for iOS performance issue

I'm creating drawing application for iOS. To draw something with a touch I used a code from this tutorial: http://www.raywenderlich.com/18840/how-to-make-a-simple-drawing-app-with-uikit
My code that I use for drawing is the following:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
NSLog(#"Moved");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(!mouseSwiped) {
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, opacity);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0];
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:opacity];
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
self.tempDrawImage.image = nil;
UIGraphicsEndImageContext();
}
My problem is the following: this code works good on simulator and on my iPhone 5, but when I run it on my iPad 2, it's not working good. I mean when the touch is moved it gets drawn on the screen only each 3 seconds or something like this (it's not continous). Moreover when I keep moving my finger without lifting my finger app crashes after sometime.
I guess it's a performance issue. But why? Do you have any idea how can I fix it?
The problem is that you keep calling [self.tempDrawImage.image drawInRect:]. This call renders an image on the CPU and is extremely slow. You're unnecessarily beginning and ending the image context. Use this code instead, I tested it on an iPad 2 and it works smoothly.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(ctxt, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(ctxt, currentPoint.x, currentPoint.y);
CGContextSetLineCap(ctxt, kCGLineCapRound);
CGContextSetLineWidth(ctxt, brush );
CGContextSetRGBStrokeColor(ctxt, red, green, blue, 1.0);
CGContextSetBlendMode(ctxt,kCGBlendModeNormal);
CGContextStrokePath(ctxt);
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
lastPoint = currentPoint;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
UIGraphicsEndImageContext();
if(!mouseSwiped)
{
self.tempDrawImage.image = nil;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(!mouseSwiped) {
UIGraphicsEndImageContext();
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, opacity);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0];
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:opacity];
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
self.tempDrawImage.image = nil;
UIGraphicsEndImageContext();
}
yes, but with this you will have a memory problem ... memory warning and crash.
if you want to try, draw between 50 and 150 lines, you can see how it causes memory problems.
if you want to fix this, in the method touchesEnded change it to this :
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIGraphicsEndImageContext(); //<----this is correct
if(!mouseSwiped) {
//UIGraphicsEndImageContext(); <--- this is the issue
and then works perfect !!

Resources