J'essaie de masquer une image avec quelque chose comme ceci:
Pourriez vous m'aider s'il vous plait?
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;
}
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 suivent 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
Le tutoriel utilise cette méthode avec deux paramètres: image
et 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 bundle:
Remarque - étonnamment, les images n'ont même pas besoin d'ê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 avoir fourni votre code, j’ai ajouté quelques chiffres sous forme de commentaires pour référence. Vous avez encore deux options. Toute cette affaire est une méthode que vous appelez quelque part. Vous n'avez pas besoin de créer les images qu'il contient: cela réduit à zéro la possibilité de réutilisation de la méthode.
Pour que votre code fonctionne. Modifiez les méthodes head (1.) en
- (UIImage *)maskImageMyImages {
Puis changez le nom de la variable dans 2. en
UIImage *maskImage = [UIImage imageNamed:@"mask.png"];
La méthode retournera vos images masquées, vous devrez donc appeler cette méthode quelque part. Pouvez-vous nous montrer le code où vous appelez votre méthode?
J'ai créé un @IBDesignable
pour que vous puissiez voir l'effet tout de suite sur votre story-board.
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
}
}
}
J'ai essayé les deux codes avec CALayer ou CGImageCreateWithMask mais aucun d'entre eux n'a fonctionné pour moi
Mais j'ai découvert que le problème est avec le format de fichier png, pas le code !!
donc juste pour partager ma découverte!
Si vous voulez utiliser
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage
vous devez utiliser 24bit png sans canal alpha
Si vous souhaitez utiliser le masque CALayer, vous devez utiliser (24 bits ou 8 bits) png avec le canal alpha où une partie transparente de votre png masquera l’image (pour un masque de dégradé lisse dégradé .. utilisez un png 24 bits avec alpha canal)
- (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.
Swift 3 XCODE 8.1
func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {
let maskRef = maskImage.cgImage
let mask = CGImage(
maskWidth: maskRef!.width,
height: maskRef!.height,
bitsPerComponent: maskRef!.bitsPerComponent,
bitsPerPixel: maskRef!.bitsPerPixel,
bytesPerRow: maskRef!.bytesPerRow,
provider: maskRef!.dataProvider!,
decode: nil,
shouldInterpolate: false)
let masked = image.cgImage!.masking(mask!)
let maskedImage = UIImage(cgImage: masked!)
// No need to release. Core Foundation objects are automatically memory managed.
return maskedImage
}
// pour utilisation
testImage.image = maskImage(image: UIImage(named: "OriginalImage")!, withMask: UIImage(named: "maskImage")!)
Version rapide de la solution acceptée:
func maskImage(image: UIImage, withMask maskImage: UIImage) -> UIImage {
let maskRef = maskImage.CGImage
let mask = CGImageMaskCreate(
CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef),
nil,
false)
let masked = CGImageCreateWithMask(image.CGImage, mask)
let maskedImage = UIImage(CGImage: masked)!
// No need to release. Core Foundation objects are automatically memory managed.
return maskedImage
}
Juste au cas où quelqu'un en aurait besoin.
Cela fonctionne parfaitement pour moi.
nous avons constaté que la réponse correcte ne fonctionnait pas maintenant et mis en œuvre une petite classe à accès restreint, ce qui permet de masquer une image dans UIImageView.
Il est disponible ici: https://github.com/Werbary/WBMaskedImageView
Exemple:
WBMaskedImageView *imgView = [[WBMaskedImageView alloc] initWithFrame:frame];
imgView.originalImage = [UIImage imageNamed:@"original_image.png"];
imgView.maskImage = [UIImage imageNamed:@"mask_image.png"];