2009-03-10 25 views
17

Ho una piccola app che consente all'utente di disegnare sullo schermo con il dito. Ho un UIImageView dove l'utente disegna, creando un CGContextRef e le varie funzioni CG draw. Io principalmente disegno tratti/linee con la funzione CGContextAddLineToPointCome disegnare un tratto trasparente (o comunque una parte chiara di un'immagine) su iPhone

Ora il mio problema è questo: L'utente può disegnare linee di vari colori. Voglio dargli la possibilità di utilizzare uno strumento "rubber" per eliminare una parte dell'immagine disegnata finora, con il dito. Inizialmente l'ho fatto usando un colore bianco per il tratto (impostato con la funzione CGContextSetRGBStrokeColor) ma non ha funzionato ... perché ho scoperto in seguito che lo UIImage sullo UIImageView aveva effettivamente uno sfondo trasparente, non bianco ... quindi finirei con un'immagine trasparente con linee bianche!

È comunque possibile impostare un colore di tratto "transparent" o c'è un altro modo per cancellare il contenuto di CGContextRef sotto il dito dell'utente, quando lo sposta? Grazie

risposta

57

Questo farà il trucco:

CGContextSetBlendMode(context, kCGBlendModeClear) 
+1

non sarebbe questo cancellare l'immagine con le linee disegnate? Cosa succede se voglio impedire che l'immagine si cancelli? e cancella solo la vernice? – Shailesh

-13
UIColor *clearColor = [UIColor clearColor]; 
1

Ho provato con:

CGContextSetStrokeColorWithColor (myContext, [[UIColor clearColor] CGColor]); 

ma che non funziona, perché sembra essere "disegno" sulla parte superiore del contesto, con un colore invisibile (e colore invisibile + qualunque colore stia disegnando = il colore su cui si sta disegnando).

L'unica soluzione che ho trovato (che non è ottimale) è:

CGContextClearRect (myContext, CGRectMake(x, y, width, height)); 

Purtroppo, questo significa che si deve tracciare una serie di rettangoli e generare la linea di te ...

6

ho finito per usare algoritmo della linea di bresenham (harkening indietro ai giorni di un tempo in cui ho dovuto scrivere le mie routine di grafica) ...

- (void) contextEraseLine:(CGContextRef) ctx from:(CGPoint)startPoint to:(CGPoint) endPoint withThickness:(int)thickness { 
    int x, cx, deltax, xstep, 
    y, cy, deltay, ystep, 
    error, st, dupe; 

    int x0, y0, x1, y1; 

    x0 = startPoint.x; 
    y0 = startPoint.y; 
    x1 = endPoint.x; 
    y1 = endPoint.y; 

    // find largest delta for pixel steps 
    st = (abs(y1 - y0) > abs(x1 - x0)); 

    // if deltay > deltax then swap x,y 
    if (st) { 
     (x0 ^= y0); (y0 ^= x0); (x0 ^= y0); // swap(x0, y0); 
     (x1 ^= y1); (y1 ^= x1); (x1 ^= y1); // swap(x1, y1); 
    } 

    deltax = abs(x1 - x0); 
    deltay = abs(y1 - y0); 
    error = (deltax/2); 
    y = y0; 

    if (x0 > x1) { xstep = -1; } 
    else   { xstep = 1; } 

    if (y0 > y1) { ystep = -1; } 
    else   { ystep = 1; } 

    for ((x = x0); (x != (x1 + xstep)); (x += xstep)) 
    { 
     (cx = x); (cy = y); // copy of x, copy of y 

     // if x,y swapped above, swap them back now 
     if (st) { (cx ^= cy); (cy ^= cx); (cx ^= cy); } 

     (dupe = 0); // initialize no dupe 

     if(!dupe) { // if not a dupe, write it out 
      //NSLog(@"(%2d, %2d)", cx, cy); 

      CGContextClearRect(ctx, CGRectMake(cx, cy, thickness, thickness)); 

    } 

     (error -= deltay); // converge toward end of line 

     if (error < 0) { // not done yet 
      (y += ystep); 
      (error += deltax); 
     } 
    } 
} 

Accidenti! Questa è una lunga strada da percorrere per creare una linea di gomme (piuttosto) goffo.

Per usarlo, fare qualcosa di simile:

- (void)eraseStart { 
    // erase lines 
    UIGraphicsBeginImageContext(drawingBoard.size); 
    ctx = UIGraphicsGetCurrentContext(); 
    CGContextDrawImage(ctx,CGRectMake(0,0,drawingBoard.size.width, drawingBoard.size.height),[drawingBoard CGImage]); 
} 

- (void)eraseEnd { 
    drawingBoard = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    [drawingView removeFromSuperview]; 
    [drawingView release]; 

    drawingView = [[UIImageView alloc] initWithImage:drawingBoard]; 
    drawingView.frame = CGRectMake(intEtchX, intEtchY, intEtchWidth, intEtchHeight); 

    [self.view addSubview:drawingView]; 
} 

Questo presuppone che si è già creato un drawingView (UIImageView) e DrawingBoard (UIImage).

Poi, per cancellare una linea, è sufficiente fare qualcosa di simile:

CGContextRef ctx = UIGraphicsGetCurrentContext(); 
[self eraseStart]; 
[self contextEraseLine:ctx from:CGPointMake (x1, y1) to:CGPointMake (x2, y2) withThickness:10]; 
[self eraseEnd]; 

(sostituzione x1, y1, x2, y2 e con i valori appropriati) ...

-2
//erase part 
if(mouseSwiped) 
{ 

//**************Working Code*************// 


UIGraphicsBeginImageContext(frontImage.frame.size); 
[frontImage.image drawInRect:CGRectMake(0, 0, frontImage.frame.size.width, frontImage.frame.size.height)]; 
CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaNone); //kCGImageAlphaPremultipliedLast); 
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10); 
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10); 
CGContextBeginPath(UIGraphicsGetCurrentContext()); 
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); 
CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x, lastPoint.y, 10, 10)); 
CGContextStrokePath(UIGraphicsGetCurrentContext()); 
frontImage.image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 


lastPoint = currentPoint; 

mouseMoved++; 

if (mouseMoved == 10) 
{ 
    mouseMoved = 0; 
} 
} 
+0

Questo non funziona - A sua volta disegna una linea marrone su una vista immagine – Shailesh