CGContextStrokePath not working when zooming and drawing images
Asked Answered
M

3

6

I'm drawing lines according to touchesMoved: method and normally it works fine. But when I zoom into the image and draw, the previously drawn lines are both displaced and keep getting more and more blurry, ultimately vanishing. I've tried using UIPinchGestureRecognizer and simply increasing the frame of myImageView (for multi-touch events only) but the problem occurs both ways. Here's the code for drawing:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 NSArray *allTouches = [touches allObjects];
 int count = [allTouches count];
 if(count==1){//single touch case for drawing line
    UITouch *touch = [touches anyObject];   
    CGPoint currentPoint = [touch locationInView:myImageView];
    UIGraphicsBeginImageContext(myImageView.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, myImageView.frame.size.width, myImageView.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 2.0);
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    lastPoint = currentPoint;
 }
else{//multi touch case
   // handle pinch/zoom
  }
}

Here is the image drawn over without zooming:

enter image description here

And this is the image depicting the problem after zooming-in with the red arrow showing the segment that was already drawn before zooming-in (as shown in previous image). The image is both blurred and displaced:

enter image description here

It can also be noticed that a part of the line drawn towards the end is unaffected and the phenomenon occurs for lines drawn back in time. I believe the reason for this is that the image size attributes are being lost when I zoom in/out which probably causes the blur and shift, but I'm not sure about that!

EDIT- I've uploaded a short video to show what's happening. It's sort of entertaining...

EDIT 2- Here's a sample single-view app focussing on the problem.

Maiocco answered 14/2, 2012 at 17:15 Comment(5)
I think this might have something to do with the contentMode of the view you're drawing in. Try UIViewContentModeRedraw?Statolith
I tried setting it for myImageView and drawImage (both are UIImageViews) but it didn't work :( ...Maiocco
@Statolith I've uploaded a video (and added in the answer) which might give you a better idea of the problem...Maiocco
I see now. That's very strange—sorry I can't help more :/Statolith
@Statolith no problem man...thnx for trying...Maiocco
M
4

I downloaded your project and I found the problem is of autoresizing. The following steps will solve it:

Step 1. Comment the line 70:

drawImage.frame = CGRectMake(0, 0, labOrderImgView.frame.size.width, labOrderImgView.frame.size.height);

in your touchesMoved method.

Step 2. Add one line of code after drawImage is alloced (line 90) in viewDidLoad method:

drawImage.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Then, the bug is fixed.

Mcgaw answered 16/5, 2012 at 5:55 Comment(0)
H
1

I implemented behavior like this in next way:

  1. You should remember all coordinates of your path (MODEL).
  2. Draw your path into temporary subview of imageView.
  3. When user starts pinch/zoom your image - do nothing, i.e path will be scaled by iOS
  4. In the moment when user has finished pinch zooming - redraw your path in correct way using your model.

If you save path as image you get bad looking scaling as result. Also - do not draw path straight to image - draw to some transparent view and split them together at the end of editing.

Higinbotham answered 14/2, 2012 at 18:22 Comment(9)
BTW, I considered your code example - and I would recommend you to implement catching/saving path separately from drawing. This may help you to avoid many troubles. Model-View-Controller pattern.Higinbotham
Actually, the bad results don't come about while zooming. It's when I draw after zooming that this weirdness happens. Do watch the short video in the question to get a better idea.Maiocco
Yes I saw video - it is some blurred effect - do not draw path straight to image - draw to some transparent view and split them together at the end of editing.Higinbotham
Have a question: do you check if frames of drawImage and myImageView are the same : [drawImage.image drawInRect:CGRectMake(0, 0, myImageView.frame.size.width, myImageView.frame.size.height)];Higinbotham
Yeah...in fact, in touchesBegan, I ensure that-drawImage.frame = myImageView.frameMaiocco
Ok...I tried by drawing in drawImage and adding it as subview but still the same problem...Maiocco
So, last advice (I already said) - separate model from drawing. Do not draw on a fly. But use MODEL (saved paths, scaling parameter...) to refresh your view. Draw into UIView but not into UIImage. Split them after end of editing.Higinbotham
It might help if you post some code snippet I can compare my code with and try to figure out what's wrong here!Maiocco
I tried your way but the problem persists. Saving the points helped me later to give the undo/redo effect, though, so thanks :)Maiocco
S
1

You are always just drawing to an image context the size of your image view - this of course gets blurry, as you do not adapt to a higher resolution when zoomed in. It would be more sensible to instead create a UIBezierPath once and just add a line to it (with addLineToPoint:) in the touchesMoved method, then draw it in a custom drawRect method via [bezierPath stroke]. You could also just add a CAShapeLayer as a subview of the image view and set its path property to the CGPath property of the bezierPath you created earlier.

See Drawing bezier curves with my finger in iOS? for an example.

Straightway answered 14/2, 2012 at 19:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.