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

标签 ios swift uiimage cgimage ciimage

我知道有很多这样的问题,但他们的解决方案对我不起作用。

注意:该图像是从 Internet 下载的。它不是取自 iPhone的相机。

我有一个 UIImage .为了进行一些图像处理操作,我使用 Metal并将图像呈现在 MTKView 中.因此,我将图像转换为 CIImage . 对图像进行所有修改后,我将其转换回 CGImage然后进入UIImage并保存它。

因此保存的图像方向错误。

我不确定它在哪一步失去了方向(当从 UIImage 转换为 CIImage 以添加到 MTKView 时,或者从 CIImage 转换为 CGImage 然后转换为 UIImage 时来保存它)。因为我不确定,下面我提供了我为每个步骤尝试过的所有内容:

用于从 UIImage 进行转换进入CIImage :

最初我只是简单地以这种方式转换图像:

let let ciImage = CIImage(image: image)

然后我尝试使用以下方式:

  let ciImage = CIImage(image: image)?.oriented(forExifOrientation: imageOrientationToTiffOrientation(value: image.imageOrientation))

这是方法imageOrientationToTiffOrientation的实现(我找到了 here ):

func imageOrientationToTiffOrientation(value: UIImageOrientation) -> Int32
{
    switch (value)
    {
    case .up:
        return 1
    case .down:
        return 3
    case .left:
        return 8
    case .right:
        return 6
    case .upMirrored:
        return 2
    case .downMirrored:
        return 4
    case .leftMirrored:
        return 5
    case .rightMirrored:
        return 7
    }
}

用于从 CIImage 进行转换进入CGImage然后进入UIImage :

我转换CIImage进入CGImage像往常一样:

let cgImage = context?.createCGImage(ciImage, from: ciImage.extent)

然后我转换cgImage进入UIImage (imageToSave)这样:

let imageToSave = UIImage(cgImage: cgImage, scale: image.scale, orientation: imageOrientation)

imageOrientationimage.scale是原始图像的方向和比例。

因此,保存的图像方向仍然错误。

有趣的是,当我打印这些图像方向原始值时,它们是相同的 0这是 .up ,但是正如我所说,保存后,方向是错误的。

我很困惑为什么会发生这种情况。如果您对如何解决此问题有任何建议,我将不胜感激您的帮助。

最佳答案

TLDR:

let uiImage: UIImage = ...
let ciImage = CIImage(image: uiImage, options:
    [.applyOrientationProperty: true,
     .properties: [kCGImagePropertyOrientation: CGImagePropertyOrientation(uiImage.imageOrientation).rawValue]])

要将 UIImageOrientation 转换为 CGImagePropertyOrientation,此代码使用 https://developer.apple.com/documentation/imageio/cgimagepropertyorientation 中的扩展名

extension CGImagePropertyOrientation {
    init(_ uiOrientation: UIImageOrientation) {
        switch uiOrientation {
            case .up: self = .up
            case .upMirrored: self = .upMirrored
            case .down: self = .down
            case .downMirrored: self = .downMirrored
            case .left: self = .left
            case .leftMirrored: self = .leftMirrored
            case .right: self = .right
            case .rightMirrored: self = .rightMirrored
        }
    }
}

长版:

我刚刚遇到了类似的问题。将 UIImage 转换为 CIImage 时,图像可能会出现方向错误:

let uiImage: UIImage = ...
let ciImage CIImage(image: uiImage) /* does not use uiImage orientation */

最简单的解决方案是使用 orientation(_:) 方法来改变方向:

let ciImage = CIImage(image: uiImage)?.oriented(CGImagePropertyOrientation(uiImage.imageOrientation))
/* uses CGImagePropertyOrientation extension (see above) */

这可能没问题,但是 orientation(_:) 方法会创建一个新图像。我认为必须有一种方法可以在没有中间对象的情况下创建正确定向的 CIImage 。确实有!虽然我在互联网上没有找到它,而且苹果也没有足够清楚地记录它,所以我把它发布在这里。 @matt 朝着正确的方向迈出了一步,但这还不够。

该解决方案已在 applyOrientationProperty 描述中“加密”。

Images can contain metadata that reveals the orientation at capture time. You can load this metadata into CIImage with imageWithContentsOfURL: or init(data:) when the captured image contains orientation metadata. Use any of the initWith:options: methods if the properties (NSDictionary of metadata properties) option is also provided.

强调了重要的部分。那是一把 key 。 此处不要混淆 optionsproperties 也很重要。 )

关于ios - UIImage 在将其转换为 CIImage、然后转换为 CGImage 并返回 UIImage 时失去其方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57516317/

相关文章:

ios - 当点击静态 UITableViewCell 时,使 UIDatePicker 随时间一起显示

ios - Swift:XCTest 类 'FirstDemoTests' 没有初始化器

ios - SpriteKit 中的 "nonuniformly scaled texture"是什么意思?

ios - 无法在 iOS 设备上运行的键盘扩展中将多个音频文件合并为一个

objective-c - 使用resizableImageWithCapInsets : image for button only works for the state set, 其他状态显示 "gap"

iOS 应用程序 : Terminated due to memory issue [Related to swiftSlowAlloc or UIImage]

ios - 将一个 NSAttributedString 的属性应用到另一个

ios - UITextView scrollEnabled = YES 在 iOS8 中设置 scrollEnabled = NO 后不工作

ios - 如何使用图像纹理设置 SKSpriteNode 的颜色?

uiimage - 从附加到AVPlayer的CALayer获取UIImage(从视频播放中提取帧)