Hvordan tegne en gjennomsiktig slag (eller uansett klart en del av et bilde) på iPhone

stemmer
18

Jeg har en liten app som lar brukeren tegne på skjermen med fingeren. Jeg har en UIImageViewhvor brukeren trekker, ved å skape et CGContextRefog de forskjellige CG drawfunksjoner. I tegner først og fremst slag / linjer med funksjonenCGContextAddLineToPoint

Nå mitt problem er dette: Brukeren kan trekke linjer av ulike farger. Jeg ønsker å gi ham muligheten til å bruke et rubberverktøy for å slette en del av bildet trekkes så langt, med fingeren. Jeg opprinnelig gjorde dette ved hjelp av en hvit farge for hjerneslag (sett med CGContextSetRGBStrokeColorfunksjon), men det fungerte ikke ut ... fordi jeg oppdaget senere at UIImageUIImageViewfaktisk hadde en gjennomsiktig bakgrunn, ikke hvit ... så jeg ville ende opp med et gjennomsiktig bilde med hvite linjer på det!

Er det allikevel å sette en transparentstrek farge eller er det noen annen måte å fjerne innholdet i CGContextRefunder brukerens finger, når han beveger seg? Takk

Publisert på 10/03/2009 klokken 09:18
kilden bruker
På andre språk...                            


6 svar

stemmer
57

Dette vil gjøre triks:

CGContextSetBlendMode(context, kCGBlendModeClear)
Svarte 27/04/2010 kl. 18:29
kilden bruker

stemmer
6

Jeg endte opp med å bruke Bresenham linje algoritme (harkening tilbake til gamle dager da jeg måtte skrive min egen grafikk rutiner) ...

- (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);
        }
    }
}

Puh! Det er en lang vei å gå for å skape en (litt) clunky viskelær linje.

For å bruke det, gjør noe sånt som:

- (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];
}

Dette forutsetter at du allerede har opprettet en drawingView (UIImageView) og Tegnebrett (UIImage).

Så, for å slette en linje, rett og slett gjøre noe sånt som:

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

(Erstatte x1, y1, x2, og y2 med passende verdier) ...

Svarte 04/04/2009 kl. 05:33
kilden bruker

stemmer
1

Jeg har prøvd å bruke:

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

men som ikke fungerer, fordi det synes å være "tegne" på toppen av sammenheng med en usynlig farge (og usynlig farge + uansett farge det er tegning på = fargen det er tegning på).

Den eneste løsningen jeg har funnet (som ikke er optimal) er:

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

Dessverre betyr at du må spore en rekke rects og generere linjen selv ...

Svarte 30/03/2009 kl. 20:59
kilden bruker

stemmer
0

Hvis du ønsker å slette bilde med berørings dette er min kode .... den unerase del ikke anbefalt det fungerer, men litt treg.

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

}
Svarte 28/03/2019 kl. 14:01
kilden bruker

stemmer
-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;
}
}
Svarte 24/08/2011 kl. 15:25
kilden bruker

stemmer
-13
UIColor *clearColor = [UIColor clearColor];
Svarte 10/03/2009 kl. 14:07
kilden bruker

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