照片编辑扩展名-将图像还原为原始图像 [英] Photo Editing Extension - Revert Image to Original

查看:94
本文介绍了照片编辑扩展名-将图像还原为原始图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发适用于iOS的照片编辑扩展程序,该扩展程序捆绑在提供相同照片编辑功能的容器应用程序中.

为了重用代码,我有一个视图控制器类,它采用必需的PHContentEditingController协议,并将其子类化,以用作应用程序扩展的主界面和容器的工作屏幕"应用程序.


在编辑扩展名上, ,该控制器的方法由照片"应用程序的编辑会话调用,如Apple文档和您可以在网上找到的各种教程中所述. 另一方面,在容器应用程序上,

,我首先通过UIImagePickerController类获得一个PHAsset实例,然后直接开始编辑会话像这样在我的工作"视图控制器上手动操作:

// 'work' is my view controller which adopts
// `PHContentEditingController`. 'workNavigation'
// embeds it.

let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { (adjustmentData) in
    return work.canHandle(adjustmentData)
}

asset.requestContentEditingInput(with: options, completionHandler: { [weak self] (input, options) in
    // (Called on the Main thread on iOS 10.0 and above)
    guard let this = self else {
        return
    }
    guard let editingInput = input else {
        return
    }
    work.asset = asset
    work.startContentEditing(with: editingInput, placeholderImage: editingInput.displaySizeImage!)
    this.present(workNavigation, animated: true, completion: nil)
})


用户完成编辑后,工作视图控制器会自行调用finishContentEditing(completionHandler:来完成会话:

self.finishContentEditing(completionHandler: {(output) in
    // nil output results in "Revert" prompt.
    // non-nil output results in "Modify" prompt. 

    let library = PHPhotoLibrary.shared()
    library.performChanges({
        let request = PHAssetChangeRequest(for: self.asset)
        request.contentEditingOutput = output

    }, completionHandler: {(didSave, error) in
        if let error = error {
            // handle error...

        } else if didSave {
            // proceed after saving...

        } else {
            // proceed after cancellation...
        }
    })
})

在编辑会话中,用户可以清除"作为调整数据传递的先前编辑,从而有效地将图像恢复为原始状态. 我注意到,如果我通过调用以nil作为参数(而不是有效的PHContentEditingOutput对象)传递给finishContentEditing(completionHandler:)的完成处理程序来完成编辑,则Photos框架将提示用户还原"图片,而不是修改"它:

func finishContentEditing(completionHandler: @escaping (PHContentEditingOutput?) -> Void) {

    guard let editingInput = self.editingInput, let inputURL = editingInput.fullSizeImageURL else {
        return completionHandler(nil)
    }

    if editingInput.adjustmentData != nil && hasUnsavedEdits == false {
        // We began with non-nil adjustment data but now have 
        // no outstanding edits - means REVERT:

        return completionHandler(nil)
    }

    // (...proceed with writing output to url...)

但是,这仅在从容器应用运行时有效.如果我尝试通过扩展使用相同的技巧(即,加载包含先前编辑内容的图像,请重置它们,然后点击完成"),我收到可怕的无法保存更改" 消息...


从照片编辑扩展程序内将以前的编辑还原为图像的正确方法是什么?

解决方案

一个月后,仍然没有答案,因此我勉强采用了这种解决方法(相对于错误警报,它还是更可取的):

当用户从照片"扩展程序用户界面中点击完成",并且该图像未应用任何编辑(因为用户重置了先前的编辑,或者未对全新的图像应用任何更改),请执行以下操作finishContentEditing(completionHandler:)中的操作:

  1. 创建调整数据,这些调整数据完全不可见(无效"效果),并将其存档为Data.

  2. 使用上面的无效效果"数据创建一个PHAdjustmentData实例,并正确设置formatVersionformatIdentifier.

  3. 根据在会话开始时传递的编辑输入(通常)创建PHContentEditingOutput实例,并设置上面创建的调整数据.

  4. 从编辑输入的inputURL属性读取未修改的图像,并将其未修改写入由PHContentEditingOutput实例的renderedContentURL属性指定的url.

  5. 调用completionHandler块,并传递编辑输出实例(通常).

结果:图像以原始状态保存(未应用任何效果),并且没有警报或错误发生.

缺点::图书馆资产仍处于已编辑"状态(因为我们传递了非零的编辑输出和调整数据,因此没有其他选择),因此下次用户尝试时要从Photos.app对其进行编辑,将出现红色的还原"按钮:

但是,选择还原"将导致图像数据没有可见变化(duh!),这可能会使用户感到困惑.

-

更新

我检查了内置的标记"扩展程序的作用:

...这与我上面的解决方法一致,所以我想这是最好的选择.

I'm developing a photo editing extension for iOS, bundled in a container app that provides the same photo editing functionality.

In order to reuse code, I have a view controller class that adopts the required PHContentEditingController protocol, and I subclassed it for use both as the main interface of the app extension, and as the "working screen" of the container app.


On the editing extension, the controller's methods are called by the Photos app's editing session as described in Apple's documentation and various tutorials you can find around the web.

On the container app, on the other hand, I first obtain a PHAsset instance by means of the UIImagePickerController class, and directly start the editing session manually on my "work" view controller like this:

// 'work' is my view controller which adopts
// `PHContentEditingController`. 'workNavigation'
// embeds it.

let options = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = { (adjustmentData) in
    return work.canHandle(adjustmentData)
}

asset.requestContentEditingInput(with: options, completionHandler: { [weak self] (input, options) in
    // (Called on the Main thread on iOS 10.0 and above)
    guard let this = self else {
        return
    }
    guard let editingInput = input else {
        return
    }
    work.asset = asset
    work.startContentEditing(with: editingInput, placeholderImage: editingInput.displaySizeImage!)
    this.present(workNavigation, animated: true, completion: nil)
})


When the user finishes editing, the work view controller calls finishContentEditing(completionHandler: on itself to finish the session:

self.finishContentEditing(completionHandler: {(output) in
    // nil output results in "Revert" prompt.
    // non-nil output results in "Modify" prompt. 

    let library = PHPhotoLibrary.shared()
    library.performChanges({
        let request = PHAssetChangeRequest(for: self.asset)
        request.contentEditingOutput = output

    }, completionHandler: {(didSave, error) in
        if let error = error {
            // handle error...

        } else if didSave {
            // proceed after saving...

        } else {
            // proceed after cancellation...
        }
    })
})

Within the editing session, the user can 'clear' the previous edits passed as adjustment data, effectively reverting the image to its original state. I've noticed that, if I finish the editing by calling the completion handler passed to finishContentEditing(completionHandler:) with nil as its argument (instead of a valid PHContentEditingOutput object), the Photos framework will prompt the user to "revert" the image instead of "modifying" it:

func finishContentEditing(completionHandler: @escaping (PHContentEditingOutput?) -> Void) {

    guard let editingInput = self.editingInput, let inputURL = editingInput.fullSizeImageURL else {
        return completionHandler(nil)
    }

    if editingInput.adjustmentData != nil && hasUnsavedEdits == false {
        // We began with non-nil adjustment data but now have 
        // no outstanding edits - means REVERT:

        return completionHandler(nil)
    }

    // (...proceed with writing output to url...)

However, this only works when running from the container app. If I try the same trick from the extension (i.e., load an image that contains previous edits, reset them, and tap 'Done') I get the dreaded "Unable to Save Changes" message...


What is the correct way to revert previous edits to an image from within a photo editing extension?

解决方案

Months later, still no answer, so I begrudgingly adopted this workaround (which is still preferable to an error alert):

When the user taps "Done" from the Photos extension UI and the image has no edits applied to it (either because the user reset previous edits, or didn't apply any changes to a brand new image), perform the following actions from within finishContentEditing(completionHandler:):

  1. Create adjustment data that amounts to no visible changes at all ("null effect") and archive it as Data.

  2. Create a PHAdjustmentData instance with the "null effect" data from above, with the formatVersion and formatIdentifier properly set.

  3. Create a PHContentEditingOutput instance from the editing input passed at the beginning of the session (as usual), and set the adjustment data created above.

  4. Read the unmodified image from the inputURL property of the editing input, and write it unmodified to the url specified by the PHContentEditingOutput instance's renderedContentURL property.

  5. Call the completionHandler block, passing the editing output instance (as normal).

The result: The image is saved in its original state (no effects applied), and no alerts or errors occur.

The drawback: The library asset remains in the 'edited' state (because we passed non-nil editing output and adjustment data, there was no other choice), so the next time the user tries to edit it from Photos.app, the red 'Revert' button will be present:

However, choosing 'revert' results in no visible changes to the image data (duh!), which can be confusing to the user.

—-

Update

I checked what the built-in "Markup" extension does:

...and it is consistent with my workaround above, so I guess this is the best that can be done.

这篇关于照片编辑扩展名-将图像还原为原始图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆