2010-08-10 26 views
35

En mi aplicación, he creado un CALayer (con algunas subcapas - el CALayer se compone de formas añadidas como subcapas).UIImage de CALayer - iPhone SDK

Estoy tratando de crear un UIImage que podré cargar en un servidor (tengo el código para esto). Sin embargo, no puedo encontrar la manera de agregar CALayer a UIImage.

¿Esto es posible? Cualquier consejo sería excelente y muy apreciado.

Muchas gracias, Brett

Respuesta

97

suena como usted quiere hacer que su capa en una UIImage. En ese caso, el siguiente método debería hacer el truco. Solo agregue esto a su vista o clase de controlador, o cree una categoría en CALayer.

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

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

    UIGraphicsEndImageContext(); 

    return outputImage; 
} 
+0

Solución impecable ... Gracias :) – oberthelot

+0

Otra respuesta más Me gustaría poder votar dos veces. Gracias Todd. –

+1

Intercambio para 'UIGraphicsBeginImageContextWithOptions (layer.frame.size, YES, 0);' – Jonny

18

respuesta de Todd es correcto, sin embargo para las pantallas retina debe haber una pequeña diferencia:

- (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

Especificando '0' para' UIGraphicsBeginImageContextWithOptions() '' s ​​'scale' arg lo predetermina para usar' UIScreen.mainScreen.scale'. _ (Según los documentos, "El factor de escala para aplicar al mapa de bits. Si especifica un valor de 0.0, el factor de escala se establece en el factor de escala de la pantalla principal del dispositivo.") _ Su respuesta funcionalmente no ofrece ninguna mejora sobre @ Todd Yandell's. –

5

He creado una extensión Swift en base a esto:

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 
    } 
} 

El uso:

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

Versión Swift 3 con un poco de error para verificar el contexto.

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

Puede usar 'defer' para manejar' UIGraphicsEndImageContext() ' –

+0

Gran sugerencia. Actualizado al aplazamiento del usuario. –

Cuestiones relacionadas