【问题标题】:UIImage from CALayer in iOSiOS中CALayer的UIImage
【发布时间】:2010-08-10 23:53:24
【问题描述】:

在我的应用程序中,我创建了一个CALayer(带有一些子层 - CALayer 由作为子层添加的形状组成)。

我正在尝试创建一个UIImage,我将能够将其上传到服务器(我有此代码)。 但是,我不知道如何将CALayer 添加到UIImage

这可能吗?

【问题讨论】:

    标签: ios objective-c uiimageview uiimage calayer


    【解决方案1】:

    听起来你想将你的图层渲染成 UIImage。在这种情况下,下面的方法应该可以解决问题。只需将其添加到您的视图或控制器类,或在 CALayer 上创建一个类别。

    Obj-C

    - (UIImage *)imageFromLayer:(CALayer *)layer
    {
      UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0);
    
      [layer renderInContext:UIGraphicsGetCurrentContext()];
      UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    
      UIGraphicsEndImageContext();
    
      return outputImage;
    }
    

    斯威夫特

    func imageFromLayer(layer:CALayer) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, layer.isOpaque, 0)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let outputImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return outputImage!
    }
    

    【讨论】:

    • 完美解决方案...谢谢:)
    • 兑换UIGraphicsBeginImageContextWithOptions(layer.frame.size, YES, 0);
    • 我会推荐使用UIGraphicsBeginImageContextWithOptions(layer.frame.size, layer.opaque, 0);
    • 如何更新它以将 CALayer 的一部分(给定图层中的矩形)渲染为图像而不是整个帧?
    • 你是救命稻草。
    【解决方案2】:

    Todd 的回答是正确的,但是对于视网膜屏幕应该有一点区别:

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

    【讨论】:

    • UIGraphicsBeginImageContextWithOptions()scale arg 指定0 默认使用UIScreen.mainScreen.scale(根据文档,“应用于位图的比例因子。如果您指定的值为 0.0,则比例因子将设置为设备主屏幕的比例因子。”) 您的答案在功能上与@Todd Yandell 相比没有任何改进。
    【解决方案3】:

    我为此创建了一个 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()
        }
      }
      

      【讨论】:

      • 可以使用defer处理UIGraphicsEndImageContext()
      • 很好的建议。更新为用户 defer。
      猜你喜欢
      • 2012-10-27
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 1970-01-01
      • 2016-05-30
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多