2010-08-10 5 views
35

В моем приложении я создал CALayer (с несколькими подслоями - CALayer состоит из фигур, добавленных в качестве подслоев).UIImage от CALayer - iPhone SDK

Я пытаюсь создать UIImage, что я смогу загрузить на сервер (у меня есть код для этого). Однако я не могу понять, как добавить CALayer в UIImage.

Возможно ли это? Любой совет будет отличным и очень оцененным.

Большое спасибо, Brett

ответ

97

Похоже, вы хотите сделать свой слой в UIImage. В этом случае метод ниже должен сделать трюк. Просто добавьте это в свой класс просмотра или контроллера или создайте категорию на CALayer.

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

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

    UIGraphicsEndImageContext(); 

    return outputImage; 
} 
+0

Безупречное решение ... Спасибо :) – oberthelot

+0

Еще один ответ, который я хотел бы отложить дважды. Спасибо Тодду. –

+1

обмен на 'UIGraphicsBeginImageContextWithOptions (layer.frame.size, YES, 0);' – Jonny

18

ответ Тодда является правильным, однако для экранов сетчатки глаза должна быть небольшая разница:

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

для '' 0 'для UIGraphicsBeginImageContextWithOptions() '' s ​​'scale' arg использует его для использования' UIScreen.mainScreen.scale'. _ (В документах «Масштабный коэффициент для применения к растровому изображению». Если вы укажете значение 0.0, коэффициент масштабирования будет установлен на масштабный коэффициент главного экрана устройства. ») _ Ваш ответ функционально не предлагает улучшения по сравнению с @ Тодда Янделла. –

5

Я создал Swift расширение на основе этого:

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

Использование:

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

Swift 3 с небольшим количеством ошибок проверки контекста.

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

Вы можете использовать 'defer' для обработки' UIGraphicsEndImageContext() ' –

+0

Отличное предложение. Обновлено для пользователя. –

Смежные вопросы