CIContext JPEG/PNG 输出函数生成空白图像
CIContext JPEG/PNG output functions producing blank images
我正在尝试将 CIImage 输出到磁盘,并且正在寻找最有效的方法。我找到了 ,这表明使用 CIContext 的 writeJPEGRepresentation
/writePNGRepresentation
方法。但是,每当我尝试使用这些方法时,它们都会生成空白图像。
对于 JPEG,它会生成纯黑色图像。 PNG 生成纯透明图像。 HEIF 方法也产生了纯黑色图像。如果我使用生成 Data
的 jpegRepresentation
或 pngRepresentation
方法而不是直接写入磁盘,结果相同。
如果我改为使用 createCGImage
渲染这些对象,然后从 CGImage 中写出数据,它们看起来很好。
知道为什么会这样吗?
这是一个说明问题的简单示例:
let ciImage = CIImage(contentsOf: photoURL, options: [CIImageOption.applyOrientationProperty: true])!
let context = CIContext()
try! context.writeJPEGRepresentation(of: ciImage, to: FileManager.default.temporaryDirectory.appendingPathComponent("testFromCIImage.jpeg"), colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, options: [:])
let cgImage: CGImage = context.createCGImage(ciImage, from: ciImage.extent)!
let uiImage = UIImage(cgImage: cgImage)
try! uiImage.jpegData(compressionQuality: 1.0)!.write(to: FileManager.default.temporaryDirectory.appendingPathComponent("testFromUIImage.jpeg"))
testFromCIImage.jpeg
显示为空白图像,与原始输入图像大小相同。 testFromUIImage.jpeg
看起来与输入图像相同。
我创建了一个 sample project 来说明这个问题,以及一些示例图片。
更新
我发现只有一种情况可以正确输出图像 - 当源图像是 PNG,并且 writeJPEGRepresentation
的 colorSpace
参数匹配源的颜色 space图片。我没有成功使用任何 JPEG,即使颜色 space 匹配。
正如您所说,这似乎是模拟器独有的问题。然而,我做了更多的挖掘并发现了以下内容:
在检查 Core Image 正在做什么时(通过设置 CI_PRINT_TREE
环境变量)我发现这棵树看起来很正常(尽管生成的图像是黑色的)。 但是,对于工作配置 什么 都没有打印!在我看来,Core Image 实际上并没有进行任何渲染,但可能 Image I/O 直接用于编写 JPG。
这让我尝试通过在上下文创建时传递 CIContextOption.useSoftwareRenderer
来强制 Core Image 使用软件渲染器(而不是其默认的 Metal 渲染器)。然而,这完全被忽略了。结果上下文仍然是 Metal 上下文...
是的,现在看来唯一可行的解决方法是通过 CGImage
。如果您能向 Apple 提交错误,那就太好了。
我正在尝试将 CIImage 输出到磁盘,并且正在寻找最有效的方法。我找到了 writeJPEGRepresentation
/writePNGRepresentation
方法。但是,每当我尝试使用这些方法时,它们都会生成空白图像。
对于 JPEG,它会生成纯黑色图像。 PNG 生成纯透明图像。 HEIF 方法也产生了纯黑色图像。如果我使用生成 Data
的 jpegRepresentation
或 pngRepresentation
方法而不是直接写入磁盘,结果相同。
如果我改为使用 createCGImage
渲染这些对象,然后从 CGImage 中写出数据,它们看起来很好。
知道为什么会这样吗?
这是一个说明问题的简单示例:
let ciImage = CIImage(contentsOf: photoURL, options: [CIImageOption.applyOrientationProperty: true])!
let context = CIContext()
try! context.writeJPEGRepresentation(of: ciImage, to: FileManager.default.temporaryDirectory.appendingPathComponent("testFromCIImage.jpeg"), colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, options: [:])
let cgImage: CGImage = context.createCGImage(ciImage, from: ciImage.extent)!
let uiImage = UIImage(cgImage: cgImage)
try! uiImage.jpegData(compressionQuality: 1.0)!.write(to: FileManager.default.temporaryDirectory.appendingPathComponent("testFromUIImage.jpeg"))
testFromCIImage.jpeg
显示为空白图像,与原始输入图像大小相同。 testFromUIImage.jpeg
看起来与输入图像相同。
我创建了一个 sample project 来说明这个问题,以及一些示例图片。
更新
我发现只有一种情况可以正确输出图像 - 当源图像是 PNG,并且 writeJPEGRepresentation
的 colorSpace
参数匹配源的颜色 space图片。我没有成功使用任何 JPEG,即使颜色 space 匹配。
正如您所说,这似乎是模拟器独有的问题。然而,我做了更多的挖掘并发现了以下内容:
在检查 Core Image 正在做什么时(通过设置 CI_PRINT_TREE
环境变量)我发现这棵树看起来很正常(尽管生成的图像是黑色的)。 但是,对于工作配置 什么 都没有打印!在我看来,Core Image 实际上并没有进行任何渲染,但可能 Image I/O 直接用于编写 JPG。
这让我尝试通过在上下文创建时传递 CIContextOption.useSoftwareRenderer
来强制 Core Image 使用软件渲染器(而不是其默认的 Metal 渲染器)。然而,这完全被忽略了。结果上下文仍然是 Metal 上下文...
是的,现在看来唯一可行的解决方法是通过 CGImage
。如果您能向 Apple 提交错误,那就太好了。