2017-08-30 6 views
1

J'ai une UIImageView que je couvre avec un masque transparent utilisant CALayer.Comment effacer une partie d'un CALayer?

Je veux pouvoir effacer des parties du CALayer avec une brosse faite à partir d'un UIImage.

Voici mon code jusqu'à maintenant pour les 2 premières étapes.

topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 
topImageView.image = [UIImage imageNamed:@"testimage2.PNG"]; 
topImageView.contentMode = UIViewContentModeScaleAspectFill; 
topImageView.userInteractionEnabled = FALSE; 
[self addSubview:topImageView]; 

CALayer *mask = [CALayer layer]; 
mask.bounds = CGRectMake(0, 0, topImageView.frame.size.width, topImageView.frame.size.height); 
topImageView.layer.mask = mask; 

enter image description here

+0

N'êtes-vous pas juste avec le dessin '.clear' sur le masque? – matt

Répondre

0

Vous devez utiliser la propriété de contenu CALayer pour modifier une partie de CALayer.

Plusieurs façons de préparer le contenu. Par exemple, vous créez un bitmap de RGBA dans un tableau UInt8, puis vous créez CGImage à partir de celui-ci.

Swift:

func createCGImageFromBitmap(bitmap: UnsafeMutablePointer<UInt8>, width: Int, height: Int) -> CGImage { 
    let colorSpace = CGColorSpaceCreateDeviceRGB() 
    let context = CGContext(data: bitmap, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) 
    let imageRef = context?.makeImage() 
    return imageRef! 
} 

Objective-C:

CGImageRef createCGImageFromBitmap(unsigned char *bitmap, int width, int height) { 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(bitmap, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast); 
    CGImageRef imageRef = CGBitmapContextCreateImage(context); 
    return imageRef; 
} 

Ici, bitmap est simplement une matrice de mémoire dans RGBARGBA ..., dont la taille est de largeur * hauteur * 4 octets. Note J'ai mis à jour la réponse originale depuis que j'ai réalisé que CGContext (données: ..) (swift)/CGBitmapContextCreate (obj-c) n'accepte pas le dernier/kCGImageAlphaLast. Il compile mais génère une erreur d'exécution w/message "erreur non prise en charge". Nous devons donc pré-multiplier alpha à RGB.

Ensuite,

Swift:

let screenScale = Int(UIScreen.main.scale) 
    let widthScaled = width * screenScale 
    let heightScaled = height * screenScale 
    let memSize = widthScaled * heightScaled * 4 
    let myBitmap = UnsafeMutablePointer<UInt8>.allocate(capacity: memSize) 
    // set RGBA of myBitmap. for your case, alpha of erased area gets zero 
    ..... 
    let imageRef = createCGImageFromBitmap(bitmap: myBitmap, width: widthScaled, height: heightScaled) 
    myBitmap.deallocate(capacity: memSize) 
    myCALayer.contents = imageRef 

Objective-C:

int screenScale = (int)[[UIScreen mainScreen] scale]; 
    int widthScaled = width * screenScale; 
    int heightScaled = height * screenScale; 
    int memSize = widthScaled * heightScaled * 4; 
    unsigned char *myBitmap = (unsigned char *)malloc(memSize); 
    // set RGBA of myBitmap. for your case, alpha of erased area gets zero 
    ..... 
    CGImageRef imageRef = createCGImageFromBitmap(bitmap, width, height); 
    free(myBitmap); 
    myCALayer.contents = CFBridgingRelease(imageRef); 

Depuis noyau graphique ne prend pas l'écran Retina en compte, nous avons besoin à l'échelle la taille du bitmap manuellement. Vous pouvez obtenir la mise à l'échelle avec UIScreen.main.scale.

Encore une note: l'axe y des graphiques de base est de bas en haut, ce qui est opposé à UIKit. Vous devez donc retourner le haut et le bas, même si c'est une tâche simple.

Ou si vous avez UIImage du masque (déjà édité), vous pouvez créer CGImage de UIImage juste avec

myCGImage = myUIImage.cgImage 
+0

Merci pour la réponse, mais seriez-vous en mesure de convertir cela en Objective C? –

+0

J'ai mis à jour ma réponse avec Objective-C. – beshio