Comment dessiner un trait transparent (ou de toute façon partie claire d'une image) sur l'iPhone

voix
18

J'ai une petite application qui permet à l'utilisateur de dessiner sur l'écran avec le doigt. J'ai un UIImageViewoù l'utilisateur tire, en créant un CGContextRefet les différentes CG drawfonctions. Je dessine d' abord coups / lignes avec la fonctionCGContextAddLineToPoint

Maintenant , ma question est la suivante: L'utilisateur peut tracer des lignes de couleurs différentes. Je veux lui donner la possibilité d'utiliser un rubberoutil pour supprimer une partie de l'image dessinée jusqu'à présent, avec le doigt. J'ai d' abord fait cela en utilisant une couleur blanche pour la course (ensemble avec la CGContextSetRGBStrokeColorfonction) , mais il n'a pas marché ... parce que j'ai découvert plus tard que le UIImagele UIImageViewavait en fait un fond transparent, pas blanc ... je voudrais donc finir avec une image transparente avec des lignes blanches sur elle!

Y at - il de toute façon de définir une transparentcouleur de contour ou est - il une autre façon d'effacer le contenu du CGContextRefsous le doigt de l'utilisateur, quand il le déplace? Merci

Créé 10/03/2009 à 10:18
source utilisateur
Dans d'autres langues...                            


6 réponses

voix
57

Ça fera l'affaire:

CGContextSetBlendMode(context, kCGBlendModeClear)
Créé 27/04/2010 à 19:29
source utilisateur

voix
6

Je fini par utiliser l'algorithme de ligne de Bresenham (harkening retour aux jours d'autrefois quand je devais écrire mes propres routines graphiques) ...

- (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! C'est un long chemin à parcourir pour créer une ligne de gomme (un peu) maladroits.

Pour l'utiliser, faire quelque chose comme:

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

Cela suppose que vous avez déjà créé un drawingView (UIImageView) et DrawingBoard (UIImage).

Ensuite, pour effacer une ligne, il suffit de faire quelque chose comme:

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

(Remplacer x1, y1, x2, y2 et avec des valeurs appropriées) ...

Créé 04/04/2009 à 06:33
source utilisateur

voix
1

Je l'ai essayé d'utiliser:

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

mais cela ne fonctionne pas, car il semble être « dessin » au-dessus du contexte avec une couleur invisible (et la couleur invisible + quelle couleur il tire sur la couleur = il dessine sur).

La seule solution que j'ai trouvé (ce qui est optimal) est:

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

Malheureusement, cela signifie que vous devez tracer une série de rects et de générer la ligne vous-même ...

Créé 30/03/2009 à 21:59
source utilisateur

voix
0

Si vous voulez effacer l'image avec une touche ceci est mon code .... la partie UnErase pas recommandé, il fonctionne, mais un peu lent.

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

}
Créé 28/03/2019 à 14:01
source utilisateur

voix
-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;
}
}
Créé 24/08/2011 à 16:25
source utilisateur

voix
-13
UIColor *clearColor = [UIColor clearColor];
Créé 10/03/2009 à 15:07
source utilisateur

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