热释光;DR:iOS照片编辑扩展无法保存对照片的更改,除非这些更改是在中使用设备拍摄的
左侧横向
方向。
我正在尝试在iOS上开发一个照片编辑扩展。
我的代码基于Xcode模板,
Apple's sample code
,以及一些在线教程。
我注意到有些照片在应用更改后无法保存;我收到一封信
警报视图
上面写着:
无法保存更改
保存时出错。请稍后再试。
在web上搜索会让我想到以下两个关于堆栈溢出的问题:
-
iOS photo extension finishContentEditingWithCompletionHandler: Unable to Save Changes
(已应用修复,在我的情况下不起作用)
-
IOS) Photo Extension Unable To Save Changes Issue
(这个问题没有有用的答案)
我尝试了几个编辑扩展,只是为了确保我的设备没有问题,发现问题出现在:
-
我的应用程序,
-
苹果自己的示例代码
,
-
一些
文学地
),而不是其他(例如。,
比特摄像机
-我希望我可以联系该应用程序的开发人员,要求一些提示。
我注意到,对于库中给定的照片资源,问题要么总是发生,要么永远不会发生。也就是说,这似乎取决于正在编辑的照片的某些属性(因此,在这种情况下,整个“稍后再试”业务毫无意义)。
finishContentEditing(completionHandler:)
方法(调用以将修改后的图像保存到框架指定的URL),并检查
PHContentEditingInput
在编辑会话开始时传递的对象。
肖像画
纵向倒置
,或
景观权
方向,只有这样。拍摄的照片
(右侧的Home按钮)可以毫无问题地保存。
苹果的示例代码是:
-
创建
CIIMage
从
fullSizeImageURL
财产
PHContentEditingInput输入
实例。
-
创建
定向拷贝
通过调用
applyingOrientation()
在上面传递
fullSizeImageOrientation
输入的属性。
-
对点2的全尺寸定向图像应用适当的CoreImage过滤器。
-
CIContext
.
-
使用上下文调用
writeJPEGRepresentation(of:to:colorSpace:)
通过在#3中获得的修改后的CIImage
renderedContentURL
从
PHContentEditingOutput
以及原作的色彩空间
CIImage
.
实际代码:
DispatchQueue.global(qos: .userInitiated).async {
guard let url = input.fullSizeImageURL
else { fatalError("missing input image url") }
guard let inputImage = CIImage(contentsOf: url)
else { fatalError("can't load input image to apply edit") }
let orientedImage = inputImage
let outputImage: CIImage
switch selectedFilterName {
case .some(wwdcFilter):
outputImage = orientedImage.applyingWWDCDemoEffect()
case .some(let filterName):
outputImage = orientedImage.applyingFilter(filterName, parameters: [:])
default:
outputImage = orientedImage
}
let context = CIContext()
if #available(OSXApplicationExtension 10.12, iOSApplicationExtension 10.0, *) {
do {
try context.writeJPEGRepresentation(of: outputImage, to: output.renderedContentURL, colorSpace: inputImage.colorSpace!)
completionHandler(output)
} catch let error {
NSLog("can't write image: \(error)")
completionHandler(nil)
}
} else {
guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent)
else { fatalError("can't create CGImage") }
guard let destination = CGImageDestinationCreateWithURL(output.renderedContentURL as CFURL, kUTTypeJPEG, 1, nil)
else { fatalError("can't create CGImageDestination") }
CGImageDestinationAddImage(destination, cgImage, nil)
let success = CGImageDestinationFinalize(destination)
if success {
completionHandler(output)
} else {
completionHandler(nil)
}
}
}
(稍作修改后发到这里。上面代码的污点存在于
分离
方法,从调度队列块中调用)
景观权
方向:
…选择苹果的示例代码图片编辑扩展:
…应用“乌贼墨”过滤器并轻敲“完成”:
…我得到了可怕的警告:
(例如,在
景观权
旋转180度,在
肖像画
旋转90度等)
单击“完成”或“取消”,然后单击“放弃更改”完成会话,图像将恢复到正确的方向:
显然,有一些陷阱,无论是我,还是开发人员
文学地
,苹果2016年的示例代码也不知道(但是
比特摄像机
是)。
发生什么事?
解决方法?
如果我用iPhone拍照
肖像画
并尝试在调试器上编辑它
全尺寸图像方向
是
.right
编辑失败了。
但是如果我使用默认工具将图像旋转180度:
…保存、再次编辑和旋转
再转180度
(或者,90+270度,但始终处于
),将其返回到
,和
然后
尝试使用扩展名编辑,现在是
全尺寸图像方向
是
.up
保存成功
. 我相信这是因为这个工具可以旋转
像素数据
而不是仅仅修改方向
元数据
(事实上,它可以在
任意角度
,不只是90度的倍数,我想它会泄露……)
当然,这需要不方便的用户交互,因此它不是一个真正的解决方法(不过,编程等效的方法是)。
我使用的是xcode10.0,上面的内容在运行ios12gm的iphone8和运行ios11.4.1的iphone5s上都得到了证实。