Come disegnare un ictus trasparente (o comunque chiara parte di un'immagine) su iPhone

voti
18

Ho una piccola applicazione che permette all'utente di disegnare sullo schermo con il dito. Ho un UIImageViewcui l'utente disegna, con la creazione di un CGContextRefe le varie CG drawfunzioni. Io principalmente disegnare tratti / linee con la funzioneCGContextAddLineToPoint

Ora il mio problema è questo: L'utente può disegnare linee di vari colori. Voglio dargli la possibilità di utilizzare uno rubberstrumento per eliminare una parte della immagine disegnata finora, con il dito. Inizialmente ho fatto questo utilizzando un colore bianco per la corsa (impostato con la CGContextSetRGBStrokeColorfunzione di), ma non ha funzionato ... perché ho scoperto più tardi che la UIImagesulla UIImageViewrealtà aveva uno sfondo trasparente, non bianco ... quindi vorrei finire con un'immagine trasparente con linee bianche su di esso!

Esiste un modo per impostare un transparentcolore del tratto o c'è altro modo per cancellare il contenuto del CGContextRefsotto dito dell'utente, quando si sposta? Grazie

È pubblicato 10/03/2009 alle 10:18
fonte dall'utente
In altre lingue...                            


6 risposte

voti
57

Ciò farà il trucco:

CGContextSetBlendMode(context, kCGBlendModeClear)
Risposto il 27/04/2010 a 19:29
fonte dall'utente

voti
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! Questo è un lungo cammino da percorrere per creare una linea di gomma (un po ') 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];

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

Risposto il 04/04/2009 a 06:33
fonte dall'utente

voti
1

Ho provato con:

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

ma questo non funziona, perché sembra essere "disegno" sulla parte superiore del contesto, con un colore invisibile (e il colore invisibile + qualsiasi colore si sta disegnando sul = colore da cui è attingendo).

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 voi stessi ...

Risposto il 30/03/2009 a 21:59
fonte dall'utente

voti
0

Se si desidera cancellare Immagine con tocco questo è il mio codice .... la parte unerase non è raccomandato che sta lavorando, ma un po 'lento.

func addNewPathToImage(){
    print("Start erasing or not erasing")

    UIGraphicsBeginImageContextWithOptions(TopImageUIImageView.bounds.size, false, UIScreen.main.scale) // or 0 for the scale

//My image is aspect fit so I need to get rect

    let aspect = TopImageUIImageView.image!.size.width / TopImageUIImageView.image!.size.height
    let viewRatio = TopImageUIImageView.bounds.size.width / TopImageUIImageView.bounds.size.height


    if aspect < viewRatio {
        let scale = TopImageUIImageView.bounds.size.height / TopImageUIImageView.image!.size.height
        let width = scale * TopImageUIImageView.image!.size.width
        let topLeftX = (TopImageUIImageView.bounds.size.width - width) * 0.5
        rect = CGRect(x: topLeftX, y: 0, width: width, height: TopImageUIImageView.bounds.size.height)
    }
    else {
        let scale = TopImageUIImageView.bounds.size.width / TopImageUIImageView.image!.size.width
        let height = scale * TopImageUIImageView.image!.size.height
        let topLeftY = (TopImageUIImageView.bounds.size.height - height) * 0.5
        rect = CGRect(x: 0.0, y: topLeftY, width: TopImageUIImageView.bounds.size.width, height: height)
    }
    ////
    context = UIGraphicsGetCurrentContext()
    TopImageUIImageView.image?.draw(in: rect)
    context?.setLineCap(.round)
    context?.setLineWidth(brushSize)



    if isErasing == true {

        context?.setShadow(offset: CGSize(width: 0, height: 0), blur: blurNumber)
        context?.setStrokeColor(UIColor.white.cgColor)
        context?.setBlendMode(.clear)


    }else{

        print("test the unerase image .... ?")
        context?.setStrokeColor(UIColor.init(patternImage: topImage.af_imageAspectScaled(toFit: CGSize(width: TopImageUIImageView.bounds.size.width, height: TopImageUIImageView.bounds.size.height))).cgColor)

    }


   // I am using these because I am using touch to define what to erase 
        context?.move(to: CGPoint(x: lastTouch.x, y: lastTouch.y))
        context?.addLine(to: CGPoint(x: currentTouch.x, y: currentTouch.y))
        context?.strokePath()
        context?.closePath() // when add this line or the "context?.beginPath" get ERROR CGContextClosePath: no current point.
        print("close the path")




        //get your image 
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        TopImageUIImageView.image = image

}
Risposto il 28/03/2019 a 14:01
fonte dall'utente

voti
-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;
}
}
Risposto il 24/08/2011 a 16:25
fonte dall'utente

voti
-13
UIColor *clearColor = [UIColor clearColor];
Risposto il 10/03/2009 a 15:07
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more