I have an iOS app that lets me erase an image with touch. It runs fine on iphone, but it lags a lot on ipad air. It uses ~40MB of memory on iphone, but ~200MB on ipad. Any ideas?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
lastTouch = [touch locationInView:self.backImageView];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
currentTouch = [touch locationInView:self.backImageView];
CGPoint eraserPoint = CGPointMake(currentTouch.x - self.eraser.size.width/2, currentTouch.y - self.eraser.size.height/2);
self.backImageView.image = [self eraseImageAtPoint:eraserPoint inImageView:self.backImageView fromEraser:self.eraser];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (UIImage *)eraseImageAtPoint: (CGPoint)point inImageView: (UIImageView *)imgView fromEraser: (UIImage *)eraser {
UIGraphicsBeginImageContextWithOptions(imgView.frame.size, NO, 0.0f );
[imgView.image drawInRect:CGRectMake(0, 0, imgView.frame.size.width, imgView.frame.size.height)];
[eraser drawAtPoint:point blendMode:kCGBlendModeDestinationOut alpha:self.eraserSpeedSlider.value];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Related
In the image below, I draw and the result is at point A, right where my finger touches.
How can I make the image appear about 40pt above my actual touch. (B)
I'm using the classic coreGraphic UITouch code, like so:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// add the first touch
UITouch *touch = [touches anyObject];
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
//transform = CGAffineTransformTranslate(self.transform, 5.0, 10.0)
// init the bezier path
self.currentTool = [self toolWithCurrentSettings];
self.currentTool.lineWidth = self.lineWidth;
self.currentTool.lineColor = self.lineColor;
self.currentTool.lineAlpha = self.lineAlpha;
[self.pathArray addObject:self.currentTool];
[self.undoStates addObject:[self.currentTool captureToolState]];
[self.currentTool setInitialPoint:currentPoint];
}
// call the delegate
if ([self.delegate respondsToSelector:#selector(drawingView:willBeginDrawUsingTool:)]) {
[self.delegate drawingView:self willBeginDrawUsingTool:self.currentTool];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// save all the touches in the path
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[self.currentTool moveFromPoint:previousPoint1 toPoint:currentPoint];
[self setNeedsDisplay];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// make sure a point is recorded
[self touchesMoved:touches withEvent:event];
CGPoint point = [[touches anyObject] locationInView:self];
[self.currentTool setInitialPoint:point];
self.draggableTextView = ((ACEDrawingDraggableTextTool *)self.currentTool).labelView;
[self.pathArray addObject:self.currentTool];
[self finishDrawing];
[self finishDrawing];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
// make sure a point is recorded
[self touchesEnded:touches withEvent:event];
}
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
// add these 2 lines below:
previousPoint1 = CGPointMake(previousPoint1.x, previousPoint1.y+40);
currentPoint = CGPointMake(currentPoint.x, currentPoint.y+40);
Basically I just want to make an eraser just like in Paint. I want to erase parts of a UIImageView just with my finger. I use the following code, however, it erases only with small strokes, while I want it to erase until I pull my finger off:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
lastTouch = [touch locationInView:bg];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGFloat brushSize = 35;
CGColorRef strokeColor = [UIColor clearColor].CGColor;
UITouch *touch = [touches anyObject];
currentTouch = [touch locationInView:bg];
UIGraphicsBeginImageContext(bg.frame.size);
CGContextRef context2 = UIGraphicsGetCurrentContext();
[bg.image drawInRect:CGRectMake(0, 0, bg.frame.size.width, bg.frame.size.height)];
CGContextSetLineCap(context2, kCGLineCapRound);
CGContextSetLineWidth(context2, brushSize);
CGContextSetStrokeColorWithColor(context2, strokeColor);
CGContextSetBlendMode(context2, kCGBlendModeClear);
CGContextBeginPath(context2);
CGContextMoveToPoint(context2, lastTouch.x, lastTouch.y);
CGContextAddLineToPoint(context2, currentTouch.x, currentTouch.y);
CGContextStrokePath(context2);
bg.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastTouch = currentTouch;
}
How should I change my code?
I have a Image view added on a view. View is using UIBezierPath and touch responder methods for drawing line upon dragging on screen. Now I would like to clip the part of image that are below the line. How can I achieve this.
I use below methods to draw line
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path moveToPoint:p];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path addLineToPoint:p]; // (4)
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesMoved:touches withEvent:event];
}
Try this:
#property (strong, nonatomic) UIBezierPath *bezierPath;
//...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
//...
self.bezierPath = [UIBezierPath bezierPath];
[self.bezierPath moveToPoint:p];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
//...
[self.bezierPath addLineToPoint:p];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesMoved:touches withEvent:event];
// Here you can call -croppedImage; method and get the image you need.
}
- (UIImage *)croppedImage
{
[self.bezierPath closePath];
UIImage *image = //Your initial image;
CGSize imageSize = image.size;
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, [[UIScreen mainScreen] scale]);
// Create the clipping path and add it
[self.bezierPath addClip];
[image drawInRect:imageRect];
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
This is a fast written code, so can be possible mistakes. Sorry for that :)
I want to know what's the approach to draw a line with a finger in a white view. I want to do an artboard, and I want begin to understand how draw a simple line or a track done with a finger. How can I do it?
I have understood your problem.
Please see the bellow code.It will use full for you.
-(void)intializeDrawImage
{
drawImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 100, 320, 320)];
[drawImage setBackgroundColor:[UIColor purpleColor]];
[drawImage setUserInteractionEnabled:YES];
[self.view addSubview:drawImage];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesBegan");
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:drawImage];
startPoint = p;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesMoved");
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:drawImage];
[self drawLineFrom:startPoint endPoint:p];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesMoved:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
-(void)drawLineFrom:(CGPoint)from endPoint:(CGPoint)to
{
drawImage.image = [UIImage imageNamed:#""];
UIGraphicsBeginImageContext(drawImage.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
[[UIColor greenColor] set];
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0f);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), from.x, from.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), to.x , to.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
I'm studying Quartz now and want to do a demo like this:
when your finger moves on the iPhone screen, it shows the track in red color。
The code is like:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_firstPoint = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
_endPoint = [touch locationInView:self];
[self setNeedsDisplay];
_firstPoint = _endPoint;
}
then
- (void)drawRect:(CGRect)rect {
// Drawing code.
CGContextRef _context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(_context, 1, 0, 0, 1);
CGContextMoveToPoint(_context, _firstPoint.x, _firstPoint.y);
CGContextAddLineToPoint(_context, _endPoint.x, _endPoint.y);
CGContextStrokePath(_context);
}
Here,_firstPoint and _endPoint are CGPoint to record positions.
However, it doesn't show the track.
I don't know what is the problem.
Please give any tips.
Finally, I'd like to consultant whether it is right to fulfill such a kind of App.
thanks!
To your point about where the collection of points making up the lines is stored, it is not stored in this example.
EDITED
Yeah, to store them, I'd just add to a NSMutableArray.
something like
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!_points) _points = [[NSMutableArray array] retain];
UITouch *touch = [touches anyObject];
[_points addObject:[NSValue valueWithCGPoint:[touch locationInView:self]];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
[_points addObject:[NSValue valueWithCGPoint:[touch locationInView:self]];
[self setNeedsDisplay];
}
The setNeedsDisplay is going to invoke the drawRect that's where you use the points and your draw methods.
you can read this tutorial to figured it out - may be it helps
http://www.ifans.com/forums/showthread.php?t=132024
i think you missed CGContextBeginPath(...) first of all
good luck!