2012-04-05 13 views
6

Mi pregunta es la misma que se menciona en here. También estoy usando dos imágenes en mi aplicación y todo lo que necesito es borrar una imagen superior mediante el tacto. Luego, borre (si es necesario) la parte borrada mediante el toque. Estoy usando el siguiente código para borrar la imagen superior. También hay un problema en este enfoque. Que es que las imágenes son grandes y estoy usando el modo de contenido Aspect Fit para mostrarlas correctamente. Cuando toco en la pantalla, se borra en la esquina, no en el lugar tocado. Creo que es necesario corregir el cálculo del punto de contacto. Cualquier ayuda será apreciada.Borrar y borrar una imagen en UIImageVIew con touch usando coregraphics

El segundo problema es cómo borrar la parte borrada por el tacto?

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

¿alguna vez encontrar una solución a esta pregunta?¿Podría compartir la solución si encuentra una? Me enfrento exactamente con el mismo problema y no puedo encontrar una solución adecuada. – Anuj

+0

Responda si tiene una solución para esto. – Muzammil

Respuesta

6

Su código es bastante ambigua: se está creando un contexto con imgTop el interior, a continuación, la mezcla con kCGBlendModeCopy el color negro? Esto provocaría que el color negro se copiara en imgTop. Supongo que quería establecer la propiedad de la capa content, entonces?

De todos modos, esta clase hace lo que necesita. Hay solo unos pocos métodos interesantes (están en la parte superior), los demás son solo propiedades o rutinas 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 

Algunas notas:

  • Esta clase conserva las dos imágenes que necesita. Tiene una propiedad touchRevealsImage para establecer el modo de dibujo o borrado, y puede establecer el ancho de la línea.

  • En la inicialización, crea un CGBitmapContextRef, escala de grises, 8bpp, sin alfa, del mismo tamaño de la vista. Este contexto se usa para almacenar una máscara, que se aplicará a la imagen de primer plano.

  • Cada vez que mueve un dedo en la pantalla, se dibuja una línea en el CGBitmapContextRef usando CoreGraphics, blanco para revelar la imagen, negro para ocultarlo. De esta forma estamos almacenando un dibujo b/n.

  • La rutina drawRect: simplemente dibuja el fondo, a continuación, crea un CGImageRef del CGBitmapContextRef y lo aplica al contexto actual como una máscara. Luego dibuja la imagen de primer plano. Para dibujar imágenes, usa - (void)drawImageScaled:(UIImage *)image, que simplemente dibuja la imagen a escala y centrada.

  • Si está planeando cambiar el tamaño de la vista, debe implementar un método para copiar o recrear la máscara con un nuevo tamaño, anulando - (void)setFrame:(CGRect)frame.

  • El método - (void)reset simplemente borra la máscara.

  • Incluso si el contexto no tiene ningún mapa de bits de canal alfa, el espacio de color en escala de grises se utiliza tiene alpha: es por eso que cada vez que se establece un color, tenía que especificar dos componentes.

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

+0

Muchas gracias, funciona bien. Y esto es justo lo que necesitaba. – gigahari

+0

¿Qué hay de Unerase? ¿Cómo puedo eliminar la imagen? –

+0

Cambia el valor de la propiedad 'touchRevealsImage'. –