Hoe maak je een transparante beroerte (of in elk geval duidelijk deel van een afbeelding) op de iPhone te trekken

stemmen
18

Ik heb een kleine app die het mogelijk maakt de gebruiker om te tekenen op het scherm met de vinger. Ik heb een UIImageViewwaar de gebruiker trekt, door het creëren van een CGContextRefen de verschillende CG drawfuncties. Ik voornamelijk trek slagen / lijnen met de functieCGContextAddLineToPoint

Nu is mijn vraag is deze: de gebruiker kan lijnen van verschillende kleuren te tekenen. Ik wil dat hij de mogelijkheid om een te gebruiken om te geven rubberhulpmiddel om een deel van de tot nu toe getrokken afbeelding te verwijderen, met de vinger. Ik in eerste instantie deed dit met behulp van een witte kleur voor de slag (ingesteld met de CGContextSetRGBStrokeColorfunctie), maar het lukte niet ... want ik ontdekte later dat het UIImageop het UIImageViewhad eigenlijk een transparante achtergrond, niet wit ... dus ik zou doen eindigen met een transparante afbeelding met witte lijnen op het!

Is er een manier om een set- transparentstroke kleur of is er een andere manier om de inhoud van de te wissen CGContextRefonder de vinger van de gebruiker, wanneer hij zich begeeft het? Bedankt

De vraag is gesteld op 10/03/2009 om 10:18
bron van user
In andere talen...                            


6 antwoorden

stemmen
57

Dit zal het lukken:

CGContextSetBlendMode(context, kCGBlendModeClear)
antwoordde op 27/04/2010 om 19:29
bron van user

stemmen
6

Ik belandde via bresenham-algoritme (harkening terug naar de dagen van weleer, toen ik moest mijn eigen graphics routines te schrijven) ...

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

Phew! Dat is een lange weg te gaan naar een (enigszins) onhandig gum regel te maken.

Om het te gebruiken, doe je iets als:

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

Hierbij wordt ervan uitgegaan dat u al een drawingView (UIImageView) en DrawingBoard (UIImage) gecreëerd.

Dan, om een ​​lijn te wissen, gewoon iets doen, zoals:

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

(Vervang x1, y1, x2, y2 en met geschikte waarden) ...

antwoordde op 04/04/2009 om 06:33
bron van user

stemmen
1

Ik heb geprobeerd met behulp van:

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

maar dat werkt niet, omdat het lijkt te zijn "trekken" op de top van de context met een onzichtbare kleur (en onzichtbare kleur + welke kleur het is op basis van = de kleur is tekening op).

De enige oplossing die ik heb gevonden (wat niet optimaal) is:

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

Helaas, dat betekent dat je moet jezelf een reeks van rects traceren en het genereren van de lijn ...

antwoordde op 30/03/2009 om 21:59
bron van user

stemmen
0

Als u wilt Afbeelding wissen met touch is dit mijn code .... de unerase deel niet aan te raden het werkt, maar een beetje traag.

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

}
antwoordde op 28/03/2019 om 14:01
bron van user

stemmen
-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;
}
}
antwoordde op 24/08/2011 om 16:25
bron van user

stemmen
-13
UIColor *clearColor = [UIColor clearColor];
antwoordde op 10/03/2009 om 15:07
bron van user

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