kneaded erasure tool on drawing app Xcode

Discussion in 'iOS Programming' started by gbenna, Jan 21, 2015.

  1. gbenna macrumors member

    Joined:
    Jul 27, 2011
    #1
    I have created a drawing app for iPhone, iPad, iPod in which the user can color on top of an outline image (coloring book). I have an erasure that removes all that is on the page, but I would like to create an erasure that would lift some but not all the color that is on the page off, much like a kneaded erasure does in real life. I have searched the net for such a thing but haven't found anything. Does anyone have any suggestions?
    I was wondering if one could use a texture filter to let only part of the erasure effect the underlying drawing but don't know how to do that.
    I have tried setting the alpha on a clearColor but there isn't one.
    HELP!
     
  2. DannyBres macrumors 65816

    DannyBres

    Joined:
    Oct 30, 2007
    Location:
    UK
    #2
    This is an insanely complex issue.

    How do you save the currently drawn lines in your model?
     
  3. gbenna, Jan 23, 2015
    Last edited by a moderator: Jan 23, 2015

    gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #3
    I have three imageViews
    1. the image that I draw on top of from my photos
    2. the saved drawing
    3. a temporary image view that I draw on

    So I draw on the temp image but constantly save to the drawing image view.

    All this works fine but when I try to erase I can't set the alpha so it doesn't erase just a little but all or none.

    this is my code

    Code:
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        
    
                self.RealImage.frame = CGRectMake(12,137,740,850);
                
                self.imageView.frame = CGRectMake(12,137,740,850);
                self.tempImage.frame = CGRectMake(12,137,740,850);
          
    
        ctr = 0;
        UITouch *touch = [touches anyObject];
        pts[0] = [touch locationInView:self.tempImage];
        
        lastPoint = [touch locationInView:tempImage];
        
    }
    
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
       
        
       self.RealImage.frame = CGRectMake(12,137,740,850);
                
                self.imageView.frame = CGRectMake(12,137,740,850);
                self.tempImage.frame = CGRectMake(12,137,740,850);
        
        
        UITouch *touch = [touches anyObject];
        CGPoint p = [touch locationInView:self.tempImage];
        currentPoint = [touch locationInView:tempImage];
        ctr++;
        pts[ctr] = p;
       
        if (ctr == 4)
        {
            pts[3] = CGPointMake((pts[2].x + pts[4].x)/2.0, (pts[2].y + pts[4].y)/2.0); 
            [path moveToPoint:pts[0]];
            [path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]];
            
            [self draw2];
            
            
            // replace points and get ready to handle the next segment
            pts[0] = pts[3];
            pts[1] = pts[4];
            ctr = 1;
        }
         NSLog(@"ctr:%d",ctr);
        lastPoint = currentPoint;
        
    }
    
    
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
       
        
        [path removeAllPoints];
        ctr = 0;
       
        
        
        UIGraphicsBeginImageContext(self.tempImage.frame.size);
        
      
        self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
        self.tempImage.image = nil;
        
        
        
        UIGraphicsEndImageContext();
        
      
       
    }
    
    - (void)draw2
    {
        
        
        UIGraphicsBeginImageContext(self.tempImage.frame.size);
        [self.tempImage.image drawInRect:CGRectMake(0, 0, self.tempImage.frame.size.width, self.tempImage.frame.size.height)];
        
        pts[3] = CGPointMake((pts[2].x + pts[4].x)/2.0, (pts[2].y + pts[4].y)/2.0); 
        [path moveToPoint:pts[0]];
        [path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]];
        
        
    
       if ([pencilString isEqualToString:@"black"]) {
            [[UIColor blackColor] setStroke];
            [path setLineWidth:w];
        }
            
        else if ([pencilString isEqualToString:@"clear"]) {
            [[UIColor clearColor] setStroke];
            [path setLineWidth:w];
             CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeCopy);
        }
       
        [path stroke];
        
        CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
        
       
        self.tempImage.image = UIGraphicsGetImageFromCurrentImageContext();
        [self.tempImage setAlpha:a];
       
        
        UIGraphicsEndImageContext();
        }
        
        
    }
    can you use a filter like a watercolor filter that lets a little of background show through but use a grainy filter that lets you erase just a little so the more grainy the less you erase but the less grainy the more you erase. How do you apply filters for different textures.
     
  4. xStep macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #4
    Thinking out loud: Perhaps you want to edit your temporary image using Core Graphics via a CGBlendMode with your erasure path.
     
  5. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #5
    Few comments:

    One way to erase is simply drawing in clearColor. Imagine you have a bitmap that is filled with clearColor. The brush draws lines into this bitmap with another color, say redColor. After that you can draw with clearColor to 'erase' the redColor. The brush you erase with could be different than the brush you draw with. It could be wider or have some different algorithm for which pixels are erased to clear based on the touch.

    Something like that could work for you if you maintain layers. The original image plus a second clear layer that is drawn into. You'd only flatten the image into a single layer as your last step.

    Another way to erase would be to fill with pixels from the original image. You keep the original image and a copy that is drawn on. To erase the drawn image you copy pixels to it from the original image based on the touch.
     
  6. gbenna thread starter macrumors member

    Joined:
    Jul 27, 2011
    #6
    So I have this pretty well done.

    I created another imageView (Copy) that copies the base imageView (Base) in touchesBegan

    Then in touchesMoved I create two paths and have path1 erase the base imageView along the stoke using
    Code:
    CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeCopy);
    and then path2 draws the copied imageView back in along the stroke using
    Code:
     [[UIColor colorWithPatternImage:theImage]setStroke];
    where "theImage" is the copied imageView.image. into another imageView (tempView)
    This tempView's alpha is set to the selected alpha on a slider selected for the kneaded erasure.

    In TouchesEnded the tempView is transferred to the base imageView and the tempView is set to nil.

    My only problem is that where the stroked path2 is draw into the tempView a small clear line is in between the path2 segments even though I use
    Code:
     [path2 setLineCapStyle:kCGLineCapButt];
    I am not sure why this is happening since when I use colorWithPatternImage and setLineCapStyle:kCGLineCapButt when I don't erase the imageView first everything works fine and there is no clear line between segments.

    I have included an attachment. Can someone figure this out?
     

    Attached Files:

Share This Page