如何将 UIImage 转换为 CIImage,反之亦然

Posted

技术标签:

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

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

UIImage *image = myImageView.image;

将图像UIImage 转换为CIImage

CIImage *cImage = [....];

如何做到这一点?

【问题讨论】:

【参考方案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 中)。因为你没有把它赋值给一个变量,所以你不能释放它,而且你在这里泄漏了相当多的内存。

以上是关于如何将 UIImage 转换为 CIImage,反之亦然的主要内容,如果未能解决你的问题,请参考以下文章

UIImage 在将其转换为 CIImage,然后转换为 CGImage 并返回 UIImage 时失去其方向

Objective c 在转换为 UIImage 时丢失了 CIImage 内存

将UIImage转换为CVPixelBufferRef

从 UIImage (Swift) 获取 CIImage

在 iOS 7 之前的项目中编译警告“不兼容的指针类型初始化 'UIImage *' 使用类型为'CIImage * _Nullable”的表达式

无法使用CIFilter从CIImage中提取UIImage