104 votes

Comment masquer une UIImageView ?

J'essaie de masquer une image avec quelque chose comme ceci :

image to be masked

Pouvez-vous m'aider ?

J'utilise ce code :

- (void) viewDidLoad {
    UIImage *OrigImage = [UIImage imageNamed:@"dogs.png"];
    UIImage *mask = [UIImage imageNamed:@"mask.png"];
    UIImage *maskedImage = [self maskImage:OrigImage withMask:mask];
    myUIIMage.image = maskedImage;
}

28 votes

Je suis la personne qui a écrit le tutoriel original. L'image du masque est juste une simple image en niveaux de gris que j'ai créée dans Photoshop. Rien de spécial à ce sujet. La zone noire devient la partie "transparente" du masque. Gardez à l'esprit que toute nuance de gris est interprétée comme un degré d'opacité. De cette manière, les masques peuvent également être des dégradés, ce qui est utile pour créer des bordures plus douces autour d'un masque.

0 votes

Ça doit être de la même taille, non ?

0 votes

Code hyper-élégant, merci. juste un lien utile si quelqu'un a besoin de recadrer une image avant de la masquer... stackoverflow.com/questions/17712797/

167voto

Il y a un moyen plus facile.

#import <QuartzCore/QuartzCore.h>
// remember to include Framework as well

CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:@"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, <img_width>, <img_height>);
yourImageView.layer.mask = mask;
yourImageView.layer.masksToBounds = YES;

Pour Swift 4 et plus, suivez le code ci-dessous

let mask = CALayer()
mask.contents =  [ UIImage(named: "right_challenge_bg")?.cgImage] as Any
mask.frame = CGRect(x: 0, y: 0, width: leftBGImage.frame.size.width, height: leftBGImage.frame.size.height)
leftBGImage.layer.mask = mask
leftBGImage.layer.masksToBounds = true

1 votes

Merci mais j'ai mis ce code sur viewDidLoad mais rien ne s'est passé !

6 votes

Vous devez définir la propriété du calque pour utiliser le masque, c'est à dire [yourImageView.layer setMasksToBounds:YES] ;

3 votes

Notez qu'il est nécessaire que ce soit un UIImageView pour cette solution. L'autre solution fonctionne uniquement avec une UIImage.

61voto

Nick Weaver Points 30418

Le tutoriel utilise cette méthode avec deux paramètres : image y maskImage vous devez les définir lorsque vous appelez la méthode. Un exemple d'appel pourrait ressembler à ceci, en supposant que la méthode est dans la même classe et que les images sont dans votre paquet :

Remarque - il est étonnant de constater que les images ne doivent même pas être de la même taille.

...
UIImage *image = [UIImage imageNamed:@"dogs.png"];
UIImage *mask = [UIImage imageNamed:@"mask.png"];

// result of the masking method
UIImage *maskedImage = [self maskImage:image withMask:mask];

...

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef maskedImageRef = CGImageCreateWithMask([image CGImage], mask);
    UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];

    CGImageRelease(mask);
    CGImageRelease(maskedImageRef);

    // returns new image with mask applied
    return maskedImage;
}

Après que vous ayez fourni votre code, j'y ai ajouté quelques chiffres en tant que commentaires pour référence. Vous avez encore deux options. Tout ceci est une méthode, que vous appelez quelque part. Vous n'avez pas besoin de créer les images à l'intérieur de celle-ci : cela réduit la réutilisabilité de la méthode à zéro.

Pour que votre code fonctionne. Changez les méthodes head ( 1. ) à

- (UIImage *)maskImageMyImages {

Ensuite, changez le nom de la variable dans 2. à

UIImage *maskImage = [UIImage imageNamed:@"mask.png"];

La méthode renverra vos images masquées, vous devrez donc appeler cette méthode à un endroit quelconque. Pouvez-vous nous montrer le code où vous appelez votre méthode ?

0 votes

Désolé ! où faut-il écrire UIImage *image code ? ! !! car sur -(UIimage *) maskeImage Le compilateur donne une erreur de redéfinition !

0 votes

Désolé, pourriez-vous télécharger un exemple de code pour moi ? Je suis confus :-s

1 votes

Pas possible, tout est là. Vous devez nous montrer comment vous appelez cette méthode, ou au moins la partie dans laquelle vous souhaitez masquer vos images et montrer le résultat.

19voto

Mark Moeykens Points 3494

Swift 3 - La solution la plus simple que j'ai trouvée

J'ai créé un @IBDesignable pour cela, afin que vous puissiez voir l'effet immédiatement sur votre storyboard.

import UIKit

@IBDesignable
class UIImageViewWithMask: UIImageView {
    var maskImageView = UIImageView()

    @IBInspectable
    var maskImage: UIImage? {
        didSet {
            maskImageView.image = maskImage
            updateView()
        }
    }

    // This updates mask size when changing device orientation (portrait/landscape)
    override func layoutSubviews() {
        super.layoutSubviews()
        updateView()
    }

    func updateView() {
        if maskImageView.image != nil {
            maskImageView.frame = bounds
            mask = maskImageView
        }
    }
} 

Mode d'emploi

  1. Créez un nouveau fichier et collez-y le code ci-dessus.
  2. Ajoutez UIImageView à votre storyboard (attribuez une image si vous le souhaitez).
  3. Sur l'inspecteur de l'identité : Changez la classe personnalisée en "UIImageViewWithMask" (nom de la classe personnalisée ci-dessus).
  4. Sur l'inspecteur des attributs : Sélectionnez l'image de masque que vous voulez utiliser.

Exemple

Masking on Storyboard

Notas

  • Votre image de masque doit avoir un fond transparent (PNG) pour la partie non noire.

12voto

Ninji Points 61

J'ai essayé les deux codes en utilisant CALayer ou CGImageCreateWithMask mais aucun d'entre eux n'a fonctionné pour moi.

Mais j'ai découvert que le problème vient du format du fichier png, PAS du code ! !!
donc juste pour partager ma découverte !

Si vous voulez utiliser

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage

vous devez utiliser 24 bits png sin canal alpha

Si vous voulez utiliser le masque CALayer, vous devez utiliser (24bit ou 8bit) png. con canal alpha où la partie transparente de votre png masquera l'image (pour un masque alpha à gradient lisse utilisez un png 24bit avec un canal alpha)

10voto

ZuYuan Points 2114
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGImageRef maskImageRef = [maskImage CGImage];

        // create a bitmap graphics context the size of the image
        CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, maskImage.size.width, maskImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(colorSpace);

        if (mainViewContentContext==NULL)
            return NULL;

        CGFloat ratio = 0;

        ratio = maskImage.size.width/ image.size.width;

        if(ratio * image.size.height < maskImage.size.height) {
            ratio = maskImage.size.height/ image.size.height;
        }

        CGRect rect1  = {{0, 0}, {maskImage.size.width, maskImage.size.height}};
        CGRect rect2  = {{-((image.size.width*ratio)-maskImage.size.width)/2 , -((image.size.height*ratio)-maskImage.size.height)/2}, {image.size.width*ratio, image.size.height*ratio}};

        CGContextClipToMask(mainViewContentContext, rect1, maskImageRef);
        CGContextDrawImage(mainViewContentContext, rect2, image.CGImage);

        // Create CGImageRef of the main view bitmap content, and then
        // release that bitmap context
        CGImageRef newImage = CGBitmapContextCreateImage(mainViewContentContext);
        CGContextRelease(mainViewContentContext);

        UIImage *theImage = [UIImage imageWithCGImage:newImage];

        CGImageRelease(newImage);

        // return the image
        return theImage;
}

Cela fonctionne pour moi.

0 votes

Merci, cette réponse est meilleure que les autres qui parlent de performance avec des images plus nombreuses et plus grandes.

1 votes

Une idée sur le masquage inverse (l'inverse du processus ci-dessus), c'est-à-dire que je veux supprimer la zone de remplissage (la rendre transparente) et la zone transparente avec le remplissage.

0 votes

Merci, ce code fonctionne mieux que le premier ! !! Mais j'ai deux problèmes : Avertissement sur "kCGImageAlphaPremultipliedLast" (j'ai fait un cast vers "CGBitmapInfo" pour le corriger) ET ne fonctionne pas pour les images rétiniennes ! ! pouvez-vous m'aider ? ?....

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X