2012-04-05 73 views
6

我的问题与here中提到的相同。我也在我的应用程序中使用两个图像,我需要的是通过触摸来擦除顶部图像。然后通过触摸删除(如果需要)删除的部分。我正在使用以下代码来擦除顶部图像。这种方法也存在问题。这是图像很大,我使用Aspect Fit内容模式来正确显示它们。 当我触摸屏幕时,它在角落而不是被触摸的地方消失。我认为触摸点计算需要一些修复。任何帮助将不胜感激。使用coregraphics删除和删除UIImageVIew中的图像

第二个问题是,如何通过触摸来删除擦除的部分?

UIGraphicsBeginImageContext(self.imgTop.image.size); 
[self.imgTop.image drawInRect:CGRectMake(0, 0, self.imgTop.image.size.width, self.imgTop.image.size.height)]; 
self.frame.size.width, self.frame.size.height)]; 
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); 
GContextSetLineWidth(UIGraphicsGetCurrentContext(), pinSize); 
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1.0); 
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy); 

CGContextBeginPath(UIGraphicsGetCurrentContext()); 
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); 
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); 
CGContextStrokePath(UIGraphicsGetCurrentContext()); 
self.imgTop.contentMode = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
+0

你有没有找到解决这个问题?如果你找到一个解决方案,你能分享一下解决方案吗我面临完全相同的问题,无法找到合适的解决方案。 – Anuj 2012-09-11 12:06:04

+0

如果您有解决方案,请回复。 – Muzammil 2012-11-02 12:14:13

回答

6

你的代码是相当含糊:你创建上下文与imgTop里面,然后用kCGBlendModeCopy黑混色?这会导致黑色被复制到imgTop。我假设你想设置图层的content属性呢?

无论如何,这个班级做你所需要的。只有一些有趣的方法(他们在顶部),其他只是属性或init...例程。

@interface EraseImageView : UIView { 
    CGContextRef context; 
    CGRect contextBounds; 
} 

@property (nonatomic, retain) UIImage *backgroundImage; 
@property (nonatomic, retain) UIImage *foregroundImage; 
@property (nonatomic, assign) CGFloat touchWidth; 
@property (nonatomic, assign) BOOL touchRevealsImage; 

- (void)resetDrawing; 

@end 

@interface EraseImageView() 
- (void)createBitmapContext; 
- (void)drawImageScaled:(UIImage *)image; 
@end 

@implementation EraseImageView 
@synthesize touchRevealsImage=_touchRevealsImage, backgroundImage=_backgroundImage, foregroundImage=_foregroundImage, touchWidth=_touchWidth; 

#pragma mark - Main methods - 

- (void)createBitmapContext 
{ 
    // create a grayscale colorspace 
    CGColorSpaceRef grayscale=CGColorSpaceCreateDeviceGray(); 

    /* TO DO: instead of saving the bounds at the moment of creation, 
       override setFrame:, create a new context with the right 
       size, draw the previous on the new, and replace the old 
       one with the new one. 
    */ 
    contextBounds=self.bounds; 

    // create a new 8 bit grayscale bitmap with no alpha (the mask) 
    context=CGBitmapContextCreate(NULL, 
            (size_t)contextBounds.size.width, 
            (size_t)contextBounds.size.height, 
            8, 
            (size_t)contextBounds.size.width, 
            grayscale, 
            kCGImageAlphaNone); 

    // make it white (touchRevealsImage==NO) 
    CGFloat white[]={1., 1.}; 
    CGContextSetFillColor(context, white); 

    CGContextFillRect(context, contextBounds); 

    // setup drawing for that context 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineJoin(context, kCGLineJoinRound); 

    CGColorSpaceRelease(grayscale); 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch *touch=(UITouch *)[touches anyObject]; 

    // the new line that will be drawn 
    CGPoint points[]={ 
     [touch previousLocationInView:self], 
     [touch locationInView:self] 
    }; 

    // setup width and color 
    CGContextSetLineWidth(context, self.touchWidth); 
    CGFloat color[]={(self.touchRevealsImage ? 1. : 0.), 1.}; 
    CGContextSetStrokeColor(context, color); 

    // stroke 
    CGContextStrokeLineSegments(context, points, 2); 

    [self setNeedsDisplay]; 

} 

- (void)drawRect:(CGRect)rect 
{ 
    if (self.foregroundImage==nil || self.backgroundImage==nil) return; 

    // draw background image 
    [self drawImageScaled:self.backgroundImage]; 

    // create an image mask from the context 
    CGImageRef mask=CGBitmapContextCreateImage(context); 

    // set the current clipping mask to the image 
    CGContextRef ctx=UIGraphicsGetCurrentContext(); 
    CGContextSaveGState(ctx); 

    CGContextClipToMask(ctx, contextBounds, mask); 

    // now draw image (with mask) 
    [self drawImageScaled:self.foregroundImage]; 

    CGContextRestoreGState(ctx); 

    CGImageRelease(mask); 

} 

- (void)resetDrawing 
{ 
    // draw black or white 
    CGFloat color[]={(self.touchRevealsImage ? 0. : 1.), 1.}; 

    CGContextSetFillColor(context, color); 
    CGContextFillRect(context, contextBounds); 

    [self setNeedsDisplay]; 
} 

#pragma mark - Helper methods - 

- (void)drawImageScaled:(UIImage *)image 
{ 
    // just draws the image scaled down and centered 

    CGFloat selfRatio=self.frame.size.width/self.frame.size.height; 
    CGFloat imgRatio=image.size.width/image.size.height; 

    CGRect rect={0.,0.,0.,0.}; 

    if (selfRatio>imgRatio) { 
     // view is wider than img 
     rect.size.height=self.frame.size.height; 
     rect.size.width=imgRatio*rect.size.height; 
    } else { 
     // img is wider than view 
     rect.size.width=self.frame.size.width; 
     rect.size.height=rect.size.width/imgRatio; 
    } 

    rect.origin.x=.5*(self.frame.size.width-rect.size.width); 
    rect.origin.y=.5*(self.frame.size.height-rect.size.height); 

    [image drawInRect:rect]; 
} 

#pragma mark - Initialization and properties - 

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    if ((self=[super initWithCoder:aDecoder])) { 
     [self createBitmapContext]; 
     _touchWidth=10.; 
    } 
    return self; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    if ((self=[super initWithFrame:frame])) { 
     [self createBitmapContext]; 
     _touchWidth=10.; 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    CGContextRelease(context); 
    [super dealloc]; 
} 

- (void)setBackgroundImage:(UIImage *)value 
{ 
    if (value!=_backgroundImage) { 
     [_backgroundImage release]; 
     _backgroundImage=[value retain]; 
     [self setNeedsDisplay]; 
    } 
} 

- (void)setForegroundImage:(UIImage *)value 
{ 
    if (value!=_foregroundImage) { 
     [_foregroundImage release]; 
     _foregroundImage=[value retain]; 
     [self setNeedsDisplay]; 
    } 
} 

- (void)setTouchRevealsImage:(BOOL)value 
{ 
    if (value!=_touchRevealsImage) { 
     _touchRevealsImage=value; 
     [self setNeedsDisplay]; 
    } 
} 

@end 

一些注意事项:

  • 该类保留你所需要的两个图像。它有一个touchRevealsImage属性将模式设置为绘制或擦除,并且可以设置线条的宽度。

  • 初始化时,它创建一个CGBitmapContextRef,灰度,8bpp,没有alpha,具有相同大小的视图。此上下文用于存储将应用于前景图像的遮罩。

  • 每次在屏幕上移动手指时,使用CoreGraphics在CGBitmapContextRef上画一条线,白色显示图像,黑色隐藏图像。这样我们就可以存储黑白图。

  • drawRect:例程简单地绘制背景,然后从CGBitmapContextRef创建CGImageRef并将其作为掩码应用于当前上下文。然后绘制前景图像。为了绘制图像,它使用- (void)drawImageScaled:(UIImage *)image,它只是绘制缩放和居中的图像。

  • 如果您打算调整视图的大小,应该实施一种方法来复制或重新创建具有新大小的蒙版,覆盖- (void)setFrame:(CGRect)frame

  • - (void)reset方法只是清除掩码。

  • 即使位图背景下也没有任何alpha通道,用于灰度色彩空间有阿尔法:这就是为什么每一个颜色设定的时间,我必须指定两个组成部分。

Sample application with <code>EraseImageView</code> class

+0

非常感谢,它效果很好。而这正是我所需要的。 – gigahari 2012-12-27 10:49:25

+0

怎么样Unerase?我怎样才能使图像不会消失? – 2012-12-28 06:09:04

+0

更改“touchRevealsImage”属性的值。 – 2013-01-03 13:00:00