2010-08-10 5 views
35

Dans mon application, j'ai créé un CALayer (avec quelques sous-couches - le CALayer est composé de formes ajoutées en tant que sous-couches).UIImage de CALayer - iPhone SDK

J'essaie de créer un UIImage que je pourrai télécharger sur un serveur (j'ai le code pour cela). Cependant, je ne peux pas comprendre comment ajouter le CALayer à un UIImage.

Est-ce possible? Tout conseil serait excellent et très apprécié.

Un grand merci, Brett

Répondre

97

On dirait que vous voulez rendre votre couche dans un UIImage. Dans ce cas, la méthode ci-dessous devrait faire l'affaire. Ajoutez simplement ceci à votre classe de vue ou de contrôleur, ou créez une catégorie sur CALayer.

- (UIImage *)imageFromLayer:(CALayer *)layer 
{ 
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0); 

    [layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return outputImage; 
} 
+0

Une solution sans faille ... Merci :) – oberthelot

+0

Encore une autre réponse que je voudrais pouvoir faire deux fois la même chose. Merci Todd. –

+1

Échange pour 'UIGraphicsBeginImageContextWithOptions (layer.frame.size, YES, 0);' – Jonny

18

réponse de Todd est correct, mais pour les écrans de la rétine il devrait y avoir une petite différence:

- (UIImage *)imageFromLayer:(CALayer *)layer 
{ 

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
     UIGraphicsBeginImageContextWithOptions([layer frame].size, NO, [UIScreen mainScreen].scale); 
    else 
     UIGraphicsBeginImageContext([layer frame].size); 

    [layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return outputImage; 
} 
+0

Spécifier '0' pour' UIGraphicsBeginImageContextWithOptions() 's' scale' arg l'utilise par défaut 'UIScreen.mainScreen.scale'. _ (Selon les docs, "Facteur d'échelle à appliquer à l'image bitmap.Si vous spécifiez une valeur de 0.0, le facteur d'échelle est défini sur le facteur d'échelle de l'écran principal du périphérique.") _ Votre réponse n'offre aucune amélioration Todd Yandell. –

5

J'ai créé une extension Swift basé pour cela:

extension UIImage { 
    class func imageWithLayer(layer: CALayer) -> UIImage { 
     UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0.0) 
     layer.renderInContext(UIGraphicsGetCurrentContext()!) 
     let img = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return img 
    } 
} 

L'utilisation:

var gradient = CAGradientLayer() 
gradient.colors = [UIColor.redColor().CGColor, UIColor.blueColor().CGColor] 
gradient.frame = CGRect(x: 0, y: 0, width: 200, height: 200) 

let image = UIImage.imageWithLayer(gradient) 
4

Version Swift 3 avec un peu d'erreur de vérification du contexte.

extension UIImage { 
    class func image(from layer: CALayer) -> UIImage? { 
    UIGraphicsBeginImageContextWithOptions(layer.bounds.size, 
    layer.isOpaque, UIScreen.main.scale) 

    defer { UIGraphicsEndImageContext() } 

    // Don't proceed unless we have context 
    guard let context = UIGraphicsGetCurrentContext() else { 
     return nil 
    } 

    layer.render(in: context) 
    return UIGraphicsGetImageFromCurrentImageContext() 
    } 
} 
+0

Vous pouvez utiliser 'defer' pour gérer le' UIGraphicsEndImageContext() ' –

+0

Grande suggestion. Mis à jour pour reporter l'utilisateur. –

Questions connexes