Jak narysować przezroczysty obrys (albo w każdym razie jasne część obrazu) na iPhone

głosy
18

Mam małą aplikację, która pozwala użytkownikowi na rysowanie na ekranie z palca. Mam UIImageVieww którym użytkownik rysuje, poprzez tworzenie CGContextRefi różne CG drawfunkcje. I przede wszystkim zwrócić Strokes / linie z funkcjiCGContextAddLineToPoint

Teraz mój problem jest taki: Użytkownik może rysować linie o różnych kolorach. Chcę dać mu możliwość korzystania z rubbernarzędzia, aby usunąć pewną część obrazu przygotowanego do tej pory, z palca. I początkowo robił to za pomocą białego koloru dla obrysu (zestaw z CGContextSetRGBStrokeColorfunkcji), ale nie wyszło ... bo odkrył później, że UIImagena UIImageViewrzeczywiście miał przezroczyste tło, biały ... więc nie chciałbym skończyć z przejrzystego obrazu z białymi liniami na nim!

Czy mimo to ustawić transparentkolor obrysu lub jest jakiś inny sposób, aby usunąć zawartość CGContextRefpod palca użytkownika, kiedy przenosi go? Dzięki

Utwórz 10/03/2009 o 10:18
źródło użytkownik
W innych językach...                            


6 odpowiedzi

głosy
57

Będzie to rade:

CGContextSetBlendMode(context, kCGBlendModeClear)
Odpowiedział 27/04/2010 o 19:29
źródło użytkownik

głosy
6

Skończyło się stosując algorytm bresenhama (harkening powrotem do dawnych czasach, gdy miałem pisać swoje własne procedury graficzne) ...

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

Uff! To długa droga do stworzenia (nieco) przylegający linię gumki.

Aby go użyć, zrobić coś takiego:

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

To zakłada, że ​​został już utworzony drawingView (UIImageView) i DrawingBoard (UIImage).

Następnie, aby usunąć linię, po prostu zrobić coś takiego:

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

(Wymienić x1, y1, x2, y2 oraz z odpowiednimi wartościami) ...

Odpowiedział 04/04/2009 o 06:33
źródło użytkownik

głosy
1

Próbowałem przy użyciu:

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

ale to nie działa, ponieważ wydaje się być „rysunek” na górze kontekście z niewidzialnego kolorze (i niewidzialnego kolorze + niezależnie od koloru jest na rysunku = kolorem to na rysunku).

Jedynym rozwiązaniem znalazłem (co nie jest optymalne) wynosi:

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

Niestety oznacza to, że trzeba śledzić serię rects i generować linię siebie ...

Odpowiedział 30/03/2009 o 21:59
źródło użytkownik

głosy
0

Jeśli chcesz usunąć obraz z dotyku to jest mój kod .... część odzyskiwania danych nie zaleca się, że działa, ale nieco powolny.

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

}
Odpowiedział 28/03/2019 o 14:01
źródło użytkownik

głosy
-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;
}
}
Odpowiedział 24/08/2011 o 16:25
źródło użytkownik

głosy
-13
UIColor *clearColor = [UIColor clearColor];
Odpowiedział 10/03/2009 o 15:07
źródło użytkownik

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