【问题标题】:How to Convert UIImage to CIImage and vice versa如何将 UIImage 转换为 CIImage,反之亦然
【发布时间】:2012-01-15 13:46:48
【问题描述】:

我正在尝试从屏幕上显示的 ImageView 获取 CIImage

UIImage *image = myImageView.image;

将图像UIImage 转换为CIImage

CIImage *cImage = [....];

如何做到这一点?

【问题讨论】:

    标签: cocoa-touch ios5 uiimage core-graphics core-image


    【解决方案1】:

    这是最兼容的方式:

    UIImage* u =[UIImage imageNamed:@"image.png"];
    CIImage* ciimage = [[CIImage alloc] initWithCGImage:u.CGImage];
    

    现在使用 ciimage...

    和 Swift 版本:

    let i1 = UIImage(named: "testImage")
    if let cgi1 = i1?.cgImage {
       let ci = CIImage(cgImage: cgi1)
       //use ci
    }
    

    (修正了 if let 语句中的错字)

    【讨论】:

    • 要从 UIImage 创建 CIImage,使用 initWithCGImage 是唯一有效的解决方案。做 'uiimagei.CIImage 没有用,它总是为零。
    【解决方案2】:
    CIImage *ciImage = [UIImage imageNamed:@"test.png"].CIImage;
    UIImage *uiImage = [[UIImage alloc] initWithCIImage:ciImage];
    

    要解决 myUIImage.CIImage[UIImageView image] 这样返回 nil 的情况,您可以改用 [CIImage imageWithCGImage:myUIImage.CGImage] – Dylan Hand

    Swift 版本:

    let ciImage = UIImage(named: "test.png")!.ciImage
    let uiImage = UIImage(ciImage: ciImage)
    

    要解决myUIImage.ciImage 返回nil 的情况,您可以改为使用CIImage(cgImage: myUIImage!.cgImage!)

    【讨论】:

    • 不管怎样,总是会调用 alloc... [UIImage imageWithCIImage:ciImage] 相当于 [[[UIImage alloc] initWithCIImage:ciImage] autorelease]
    • 小心点。如果 UIImageCGImageRef 初始化,CIImage 将是 nil,这将不起作用。
    • 使用...WithCIImage: 创建的UIImage 在调整大小时确实存在一些问题,因为大多数带有UIImage 的框架都需要CGImage。所以你需要先用createCGImage:fromRect:或类似的东西来渲染它。
    • 要解决myUIImage.CIImage 返回nil 的情况,您可以改为使用[CIImage imageWithCGImage:myUIImage.CGImage]
    • 如果可能,最好使用 imageWithCIImage:scale:orientation 而不是 imageWithCIImage CIImage* aCIImage = [CIImage imageWithData:imageData]; UIImage* anImage = [UIImage imageWithCIImage:aCIImage scale:1.0orientation:orientation];
    【解决方案3】:

    在将 UIImage 转换为 CIImage 时,我遇到了两种不同的情况,有时它是零,有时不是。下面的代码解决了它:

    CIImage *ciImage;
    ciImage=[[CIImage alloc] initWithImage:imageToConvert];
    if (ciImage==nil)
        ciImage=imageToConvert.CIImage;
    

    【讨论】:

      【解决方案4】:

      斯威夫特 3/4

      UIImage > CIImage

      let ciimage = CIImage(image: image)

      https://developer.apple.com/documentation/uikit/uiimage/1624090-init

      CIImage > UIImage

      let image = UIImage(ciImage: ciimage)

      https://developer.apple.com/documentation/coreimage/ciimage/1624119-init

      【讨论】:

        【解决方案5】:

        changx 答案的 Swift 示例:

        guard let ciimage = CIImage(image: uiimage) else { return }
        let image = UIImage(CIImage: ciimage)
        

        【讨论】:

        • 它不转换任何东西,如果不是从 ciimage 构造的,将返回 nil
        • 你不需要上下文吗?
        【解决方案6】:
        func toCIImage(image: UIImage) -> CIImage {
            return image.CIImage ?? CIImage(CGImage: image.CGImage!)
        }
        
        func toUIImage(image: CIImage) -> UIImage {
            return UIImage(CIImage: image)
        }
        

        【讨论】:

        • 它不转换任何东西,如果不是从 ciimage 构造,将返回 nil
        【解决方案7】:

        这是我在项目中使用的完整代码示例。

        - (UIImage *)makeUIImageFromCIImage:(CIImage *)ciImage {
            CIContext *context = [CIContext contextWithOptions:nil];
            CGImageRef cgImage = [context createCGImage:ciImage fromRect:[ciImage extent]];
        
            UIImage* uiImage = [UIImage imageWithCGImage:cgImage];
            CGImageRelease(cgImage);
        
            return uiImage;
        }
        

        CIImage 基本上是图像的配方。如果您尝试直接从CIImage 转换为UIImage,将会遇到问题。比如调用

        NSData * UIImageJPEGRepresentation (
           UIImage *image,
           CGFloat compressionQuality
        );
        

        将返回nil

        【讨论】:

          【解决方案8】:

          虽然 Changxing Wang 的回答实际上是正确的,但 Apple 表示 UIImage.CIImage 并不总是有效。具体来说,来自 PocketCoreImage:

          // Create a CIImage from the _inputImage.  While UIImage has a property returning
          // a CIImage representation of it, there are cases where it will not work.  This is the
          // most compatible route.
          _filteredImage = [[CIImage alloc] initWithCGImage:_inputImage.CGImage options:nil];
          

          Apple 还使用以下内容,但对我不起作用:

          [UIImage imageWithCIImage:_filteredImage] 
          

          我个人的实现,改编自 this post 对我有用:

          // result is a CIImage, output of my filtering.  
          // returnImage is (obviously) a UIImage that I'm going to return.
          CIContext *context = [CIContext contextWithOptions:nil];
          UIImage *returnImage = 
          [UIImage imageWithCGImage:[context createCGImage:result fromRect:result.extent]];
          

          【讨论】:

          • 在设置上下文时要小心,除非您绝对必须这样做,因为这通常是一项昂贵的任务。我建议设置为@property 并在处理图像转换之前创建它。但是,如果您只这样做一次,上述解决方案应该可以正常工作。
          • 创建的 CGImageRef 将被保留。您必须保持对它的引用,并在创建 UIImage 后调用 CGImageRelease(cgimage)。否则内存会泄露
          • 您的代码泄漏:[context createCGImage...] 创建了一个必须释放的 CGContextRef(即使在 ARC 中)。因为你没有把它赋值给一个变量,所以你不能释放它,而且你在这里泄漏了相当多的内存。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-07-27
          • 2021-06-10
          • 2012-03-24
          • 2018-06-28
          • 2010-12-04
          • 1970-01-01
          相关资源
          最近更新 更多