Wie ein transparentes Hub (oder jedenfalls klar Teil eines Bildes) auf dem iPhone ziehen

stimmen
18

Ich habe eine kleine Anwendung , die der Benutzer ermöglicht , auf dem Bildschirm mit dem Finger zu ziehen. Ich habe ein , UIImageViewwo der Benutzer zeichnet, durch eine Erstellung CGContextRefund die verschiedenen CG drawFunktionen. I hauptsächlich Hübe / Linien mit der Funktion drawCGContextAddLineToPoint

Nun mein Problem ist folgende: Der Benutzer kann Linien in verschiedenen Farben zeichnen. Ich will ihm die Möglichkeit geben , einen zu verwenden rubberWerkzeug , einen Teil des Bildes so weit, mit dem Finger gezogen zu löschen. Ich habe anfangs dies durch eine weiße Farbe für den Hub verwenden (mit der eingestellten CGContextSetRGBStrokeColorFunktion) , aber es hat nicht geklappt ... weil ich später , dass die entdecken UIImageauf dem UIImageViewtatsächlich hatte einen transparenten Hintergrund, nicht weiß ... so würde ich am Ende mit einem transparenten Bild mit weißen Linien auf mich!

Gibt es trotzdem eine setzen transparentStrichfarbe oder gibt es eine andere Möglichkeit , den Inhalt der löschen CGContextRefunter dem Finger des Benutzers, wenn er es sich bewegt? Vielen Dank

Veröffentlicht am 10/03/2009 um 10:18
quelle vom benutzer
In anderen Sprachen...                            


6 antworten

stimmen
57

Dies wird den Trick:

CGContextSetBlendMode(context, kCGBlendModeClear)
Beantwortet am 27/04/2010 um 19:29
quelle vom benutzer

stimmen
6

I ended Bresenham-Algorithmus unter Verwendung von bis (harkening zurück zu dem alten Zeiten, als ich musste meine eigenen Grafikroutinen schreiben) ...

- (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! Das ist ein langer Weg zu gehen, um eine (etwas) klobig Radiergummi Linie zu erstellen.

Um es zu nutzen, so etwas wie:

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

Dies setzt voraus, Sie haben bereits eine drawingView (UIImageView) und DrawingBoard (UIImage) erstellt.

Dann eine Linie zu löschen, tut einfach so etwas wie:

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

(Ersetzen x1, y1, x2 und y2 mit den entsprechenden Werten) ...

Beantwortet am 04/04/2009 um 06:33
quelle vom benutzer

stimmen
1

Ich habe versucht mit:

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

aber das nicht funktioniert, weil es scheint, „Zeichnung“ auf den Zusammenhang mit einer unsichtbaren Farbe (und unsichtbarer Farbe +, was Farbe auf zeichnet = die Farbe ist es Zeichnung auf).

Die einzige Lösung, die ich gefunden habe (was nicht optimal ist) ist:

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

Leider bedeutet, dass Sie eine Reihe von Rects zu verfolgen haben und die Linie selbst erzeugen ...

Beantwortet am 30/03/2009 um 21:59
quelle vom benutzer

stimmen
0

Wenn Sie Bild mit Touch löschen wollen, ist dies mein Code .... der unerase Teil nicht zu empfehlen, es funktioniert, aber etwas langsam.

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

}
Beantwortet am 28/03/2019 um 14:01
quelle vom benutzer

stimmen
-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;
}
}
Beantwortet am 24/08/2011 um 16:25
quelle vom benutzer

stimmen
-13
UIColor *clearColor = [UIColor clearColor];
Beantwortet am 10/03/2009 um 15:07
quelle vom benutzer

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