大多数浏览器和
Developer App 均支持流媒体播放。
-
iOS 摄影功能改进
人们喜欢用 iPhone 拍照。实际上,它是全世界广受欢迎的相机,而摄影类 app 能够强化这一体验。探索新的 AVFoundation Capture API,它们可以用来拍摄实况照片、从相机提取 RAW 图像数据以及拍摄广色域照片。
资源
相关视频
WWDC21
WWDC16
-
下载
IOS PHOTOGRAPHY的新特性 早上好 早上好各位 欢迎来到501会话 我是Brad Ford 我在Apple的Core Media和 AV Foundation Capture团队工作
本次会议全是关于iOS相机的 希望你们现在都已经知道了 这是世界上最流行的相机 本次会议也是关于摄影的 如果你开发一个摄影的应用 或是正考虑开发一个摄影应用 那么这对你来说是个不错的OS 我觉得你和iOS 10 很快就能交上朋友 今天我们将把注意力集中到 AV Foundation框架 它是我们最底层 并且最强大的访问相机的框架 AV Foundation 有着广度和深度 如果你是iOS拍照的新手 我邀请你看下列过去 WWDC 的相机主题演讲视频 它们会给你听今天的 演讲打下良好的基础 另外 你可以看到我优雅地老去
在接下来的58分钟里 我们将要进行这些 我会展示全新的 AVCaptureOutput 用来捕捉拍摄内容 然后我们会关注四个特性 我们会关注Live Photos 你们将学会如何用 你的应用拍摄Live Photos 就如Apple的相机应用一样 你们将学会如何拍摄 原生RAW格式图片 并将它们保存为DNG文件 其在iOS上首次出现 你们将学到如何获得预览或者缩略图 为你的常规图片拍摄 以获得一个更具响应性的UI
最后 你会学到如何用 宽色域拍摄漂亮的栩栩如生的照片 让我们现在开始吧 我们先快速回顾一下 AV Foundation的捕获类是怎么工作的 我们拍照的宇宙中心 是AVCaptureSession 你告诉这个对象开始或结束运行 它需要一些输入 来使其可以干些有用的事 像是相机或是麦克风这类输入 它们给会话提供了数据 它也需要输出来接收数据 比如一个StillImageOutput 可以捕捉静态的图像 或是一个QuickTimeMovieFileOutput 可以用来录制Quicktime影片 还有connections 它们被作为AVCaptureConnections 在API中所呈现 这是我们的对象概览图 你们该看出来我们如何 把所有东西整合到一起 所有我刚提到的这些特性 都与拍摄静态图片有关 所以你可能预计今天会花很长时间 在AVCaptureStillImageOutput上 但是你错了
今天介绍iOS 10中 全新的CaptureOutput 它叫做AVCapturePhotoOutput 值得强调的是现如今我们的照片 可不止是静态的图片
AVCapturePhotoOutput解决了 AVStillImageOutput的设计难题 从四个主要方面 它以一个函数式的编程模型为主要特色 它对于可变和不可变的 数据间有明确的划分 我们将照片设置信息封装到 一个特有的对象作用到其自身 PhotoOutput可追踪照片 从请求到完成的全过程 通过一个回调的代理式接口 最后 它解决了 你在早先拍摄阶段不确定的图片设置 因此你知道你会得到什么 让我们再多讲一些最后一个特性
AVCapturePhotoOutput 看起来是这样的 即便有着诸多的新特性 它仍是个简洁的接口 甚至比AVCaptureStill ImageOutput还要小 它有一个只读属性的小集合 来告诉你是否支持一个特性 像是 isLivePhotoCaptureSupported 它有一个更小的可写属性的集合 让你可以参与进来 当某个特性被支持时 有些拍摄特性会 影响拍摄渲染管道的建立 所以你们要提前指明它们 其中一个是 isHighResolutionCapture 如果你想拍摄高分辨率的照片 像是在iPhone 6s上 五百万像素的自拍 你得先采用这个特性 在调用AVCapture session的 startRunning之前 最后 你可以调用一个简单的方法 来开始拍摄照片 仅仅一个动词 你可能会问 所有那些相片生成状态怎么办 我怎么请求闪光灯拍摄 我怎么获得BGRA 我怎么获得静态图片防抖 这些还有一些其他特性都被移动到 一个叫做AVCapturePhoto Settings的新对象中 这个对象包含所有这些设置 关于拍摄一张照片的请求 把它想成是个列表项可供选择 像是当你在Apple线上 商店买Mac的时候 你在网上表格里填上所有你想要的特性 然后点击提交订单按钮 提交订单就像是调用 capturePhoto 将AVCapturePhotoSettings 作为你所传的第一个参数 当你在网上下单时 商店需要你的电邮地址 来和你沟通订单的信息
在AVCapturePhotoOutput世界 你所提供的电邮地址就是遵从 AVCapturePhotoCapture Delegate协议的对象 这个delegate会被回调 作为和你的拍照发生相关的事件 这个对象是传给 CapturePhoto第二个参数
那么AVCapturePhotoSettings 有什么好处呢 首先 它们是原子性的 所有设置都被封装到一个单一对象 所有的设置都不可能会不同步 因为它们不是 AVCapturePhotoOutput的属性 而是每一设置相关的对象 它们是独一无二的 每个照片设置实例都有唯一的ID属性 你只允许使用一个照片设置一次 并且不能再用 因此你每次拍照请求 将收到正好一组结果
在附加一组设置请求拍照后 你可以坚持不变动 并验证它们返回给你的结果 就有点像做了一个 你在线订单表格的备份
那么相片委托有什么好处呢 它是一个单一的回调函数集合 而且又是随着每个照片设置而变 序列是被记录下来的 你可以明确知道你将获得哪个回调函数 何时 以什么顺序 并且它是个用来解决不确定设置的手段 我想这点我得再多解释一点 假如说你的应用在时间轴上的 这个位置请求照片
你指明照片设置是带有自动闪光灯 和自动静态图片防抖 我把“静止图像稳定”缩写成SIS 以便能在幻灯片上显示的更好 你告诉PhotoOutput 我想使用闪光灯或者SIS 但是只在你需要的时候 还有它们适合于当前场景的时候 很快你提出了请求 PhotoOutput 会调用你委托的第一个回调函数 也就是willBeginCapture ForResolvedSettings 这个回调函数永远都是第一个被调用 它就有点像是 你从Apple收到的礼节性邮件 告诉你我们已经收到了你的订单 我们会发送给你什么 这个回调函数传给你一个实例 实例是一个新对象的 叫做 AVCapturePhotoResolvedSettings 它就像你填写的照片设置 不同的是所有问题都解决了 它们有着相同的唯一ID 你未确定和决定的版本 共享一个唯一ID 以便你将它们一起比较 它也告诉你照片的输出 为你挑出了什么特性 注意 在这个例子中 闪光灯被设定为开 SIS被设定为关 我们现在很明显是处在极度弱光环境 像是这个会议室 接下来的回调函数是 willCapturePhotoForResolvedSettings 它是正好在拍照片的时候被送到 或是当虚拟相机快门正在闭合 并且播放了快门声的时候 如果你想播放一个快门动画效果 那么这正是时候 接下来马上就是 didCapturePhotoForResolvedSettings 就在图像被完全曝光呈现出来 而且虚拟快门开启之后
然后你要等一下因为图像正在被处理 加上所有你要求的特性 当照片最后处理完成时 你获得didProcessing PhotoSampleBuffer这个回调函数 还有你一直在等的 ImageSampleBuffer 耶 就像是崭新的 Mac送到了你的门口 最后 你获得的回调函数是 didFinishCaptureForResolvedSettings 它肯定是最后被送达的 它就像是你收到的 来自Apple的回访邮件 告诉你所有包裹已经送到了 与你打交道非常愉快 完毕 现在是你清理图片生成 中间阶段存储的好时机
让我们详细讨论下那些委托 回调函数会追踪一个单一拍照请求 照片输出会保留一个 对你委托的弱引用 所以它不会一直给你保留那个对象 记着在你的代码里给它保留一个强引用 所有在这个协议里的回调函数 都被标为可选的 但其中有些在runtime 会变为必需 这取决于你的照片设置 例如 当你正拍一个压缩的跑步图片时 你的委托需要在你获得 照片的时候就实现一个回调函数 否则 我们就会无处送达它 此规则在AVCapturePhotoOutput.h 头文件中就明确写出了
所有回调函数都会传一个 ResolvedPhotoSettings对象的实例 就是我告诉你们的那个 因此你总会知道你将要得到什么 或是你刚刚得到了什么
说到设置 我们来看段代码 它展示了 如何初始化照片拍摄 利用AVCapturePhotoSettings 的诸多特性 首先第一个 takeHighResolutionPhoto 如我前面所说 iPhone 6s的前置摄像头 支持五百万像素的高分辨率自拍 但是它不能支持 五百万像素的连续流畅拍照 它只支持单个高像素的定格照 所以你必须创建 一个PhotoSettings对象 并设置启用 HighResolutionPhotoCaptureEnabled 这样你就生成了带有参数的结构体 AVCapturePhotoSettings 它默认将输出格式设为JPEG 并启用了静态图像防抖 然后我将isHighResolution PhotoEnabled设为真 并调用CapturePhoto 在第二个例子 takeFlashPhoto中 注意flashMode 现在是settings对象的一个属性了 如果你过去用过 StillImageOutput 你就会知道Flash原来是 AVCaptureDevice的一部分 所以这会产生问题 就是你需要访问 两个不同的对象来设置settings 现在它是单独一个对象的一部分了 太棒了 最后一个例子用了一个挺复杂的 AVCapturePhotoSettings的结构体 这回我们要传递我们想要的输出格式 在这里 我们想要非压缩的BGRA格式 我们要建立 一个CV像素缓存属性的字典 然后将其作为 AVCapturePhotoSettings的参数传递 这样就行了 当你调用capturePhoto时 AVCapturePhotoOutput 会验证你的设置 来确保你不是在请求一些荒唐的东西 它将保证自治性 也将确保你所请求的东西真的被支持 如果不被支持 它会抛出一个异常
Result设置 如你所想是完全不能变动的 所有属性都是只读的 它们仅供你参考用 而且这是函数式编程不可变的部分 它有一个唯一ID来让你和 你的未设置的 settings对象作比较 这是个不错的特性 它让你在没得到你的照片前 就知道照片的尺寸 所以你能提前计划 做一些分配 或是其他你需要做的事
它会告诉你flash 被设为on还是off 静态图片防抖是被设为on还是off
它也支持包围曝光拍摄 这是一种你请求 多张图片时的特殊拍摄手法 有时候伴随着不同的曝光值 例如 可能是这么来做的 如果你想将多张曝光图片合并在一起 来生成像是HDR这样的效果 我在2014年的508会议上 讲了很多关于这类拍摄的问题 去看下那个视频来回想一下 在AVCaptureStillImageOutput中 我们支持自动包围曝光和定制包围曝光 而请求包围曝光的新方法是 初始化一个 AVCapturePhotoBracketSettings 它像是照片设置但它是一个子类 它有你额外所需的东西 用来完成包围曝光拍摄 当你想创建一个包围曝光时 你要声明一个数组 数组是AVCaptureBracketed StillImageSettings的 这是个从AVCaptureStillImageOutput 时代就有的对象 你给每个曝光表明其中一个值 例如 -2EV +2EV 0EV 如果你是用iPhone 6s 或者6s Plus 你可以选择启用镜头防抖 利用isLensStabilizationEnabled属性 请你回忆下我之前幻灯片 展示给你们的时间轴 照片被传到didFinishProcessing PhotoSampleBuffer回调函数 当你请求三张图片的包围曝光时 该回调函数会被调用三次 每张图片一次 第五个参数告诉你是哪个包围曝光设置 在这个图片请求中与之协同的
我们很喜欢新的 AVCapturePhotoOutput 所以我们想让你马上就用它 因此我们在iOS10中不赞成使用 AVCaptureStillImageOutput 和其他所有AVCaptureDevice中 闪光灯相关的属性 这才是你应该用的 如我所说 闪光灯拍摄的一部分被打包到 相片设置中 它是一个更好的程序接口 尽快的使用它吧
最后一项是 在我们在说下面之前说下photo的好处 它们使书签功能更容易 即时的设置设定 有把握的请求追踪 它对Apple来说也有益处 因为它对我们来说 像是个可扩展的回调函数调色板 我们可以在将来加入 新的方法并回调给你 最后一点对于 接下来我要说的特性很重要 我要说的就是Live Photos Apple.com上有关于何谓 Live Photos好的宣传广告 静态照片捕捉到的是瞬间凝结的记忆 而有了Live Photos 你能将这些瞬间变成 令人难忘 鲜活生动的回忆
Live Photos的美妙之处在于 它们会珍藏你留存于 记忆深处的美好瞬间 在这张照片里 这是张不错的静态照片 巨大恶心的沙蟹 这是我外甥从沙滩上挖出来的 一张不错的照片 如果我3D touch它
好了 现在我想起来了 那天太冷了 他从来没到过海边 他的嘴唇都冻青了 他在海水里时间太长 手都一直在发抖 我还在开始时候听到我哥哥的声音 所有这些都帮我进行了回忆 因为我更多的感官被唤醒了 人们发现了各种新的方式 把Live Photos 当做艺术创作的媒介使用 这张是一个旋转的自拍 我们的相机产品团队 把它叫做甜甜圈自拍
要完成它可是相当有难度的 有张用Live Photo拍的 正在旋转的转椅也很流行 看看那张吧 我是个展现惊喜的 live photo的大粉丝 不幸的是 我们孩子们也是
一个三秒的窗口实在太有诱惑力了 对于我这么一个天生的 吓人照片爱好者来说 Live Photos是从 Apple设计工作室思考体验中诞生 其诞生的前提是 即便我们现在有了这么多好的屏幕 来分享和观看内容 照片体验已经保持静态有150年了 我们划过屏幕浏览的那些JPEG文件 只不过就是数字版本的 那些我们留存在鞋盒中相纸的化学药剂 而它仍然是 人们保存他们回忆的主要方式 所以难道我们不能做得更好么 经过了很多的试验和原型体验 我们得出了这个新的媒体体验 一个时刻或是一个记忆 首先最重要的是它还是一张静态照片 它仍然和以前照片的质量一样好 它是一张1200万像素全分辨率的 静态JPEG图片 它与非LIve Photos 有着相同的质量 让我再强调一遍 Live Photos有Apple 非Live Photos的一切优点 所以你把它打开没有牺牲任何东西
另一个很棒的点子是平滑拍摄 这意味着你不需要学习任何新的东西 你就如你原来一样拍摄照片就可以 还是那样 定景 按快门 不用考虑别的
一张Live Photo 同样也是一段记忆 它能比静态图片调动更多感觉 它可以帮你唤起回忆
所以它就像是一部短电影 3秒的电影 1.5秒是静态图之前发生的事 1.5秒是之后的 我们能以 屏幕分辨率或者1080p拍摄它
而且它包含音频
我们还在持续改进它的设计 iOS9.1中我们加入挺棒的特性 自动裁剪Live Photos 以防你你冲着你的鞋子 或者口袋做出挥动的动作 我们会自动裁掉这些 去除掉 你不想在影片中看到的部分 在iOS 10中 我们加入新特性让它变得更好 现在所有的Live Photo 影片都是防抖的了
另一个iOS10的新特性是 拍摄时可以播放音乐 如果你正在放音乐
是啊 这个特性不错 我也挺喜欢的
为了让它成为一个时刻也是一段记忆 如你所料的 Live Photo有两部分组成 JPEG及 QuickTime电影文件 这两部分共享一个通用的 UUID以此来连系它们 JPEG文件的UUID被存储在 Apple Maker Note里 影片资源 也就是我说的 通常三秒长 有视频轨 大概是1080p 有着3比1的宽高比 它包含一个带有示例的定时元轨道 就相当于是对应静态图片的时间 在影片的时间轴上 它还包含了一些上层影片的元数据 可以用来与JPEG的元数据来配对 这叫做QuickTime内容识别器 它的值是一个UUID风格的流
需要怎样 才能拍摄Live Photos呢 在AVCapturePhotoOutput里 有一个属性叫 isLivePhotoCaptureSupported 你得确保它被支持 它不是在所有设备上都被支持的 目前它只支持 AVCaptureSessionPresetPhoto
你要使用AVCapturePhotoOutput .isLivePhotoCaptureEnabled 将其设为真 你需要在你开始运行会话之前启用它 否则会造成会话破坏性的重新配置 你绝对想避免这麻烦 如果你在你的Live Photo 影片中播放音频 你要为麦克风添加一个 AVCaptureDeviceInput 这很重要 不要忘了 而且不支持同时录制 使用AVCaptureMovieOutput 录制的常规电影 和Live Photos 因此如果在会话的拓扑图上 有一个影片文件输出 它会使Live Photo拍摄禁用
可按通常方式配置 LivePhotoCapture 它有默认的结构体 不过你要额外声明一个 LivePhotoMovieFileURL 在这里我们会写入影片 并且它必须在你的沙盒内 你还得能访问它 你不需要声明任何的 livePhotoMovieMetadata 但是如果你想的话也可以 在此我举个使用 author元数据的例子 我把自己设为author 以便全世界都知道这是我的影片 你也可以加些有趣的东西 像是往你的影片里加入GPS标签 让我们谈谈跟 Live Photo有关的委托方法 如我之前所说的 我们有个可扩展的调色板 关于委托回调函数的 我们将会用到它 当拍摄Live Photo时 你的第一个回调函数让你知道 有一个Live Photo 将会被录制 借由告诉你影片定好的尺寸 看到了吗 你不仅调整了照片的尺寸 你还知道了Live Photo 的尺寸会是多大 你收到了预期的回调函数 还包含了一张和以前一样 会保存在内存中的JPEG文件 不过我们会给你一些新的东西 一个Live Photo影片 实际就是三秒的影片 在其正中间夹着一张静态图片 这意味着在你的拍摄请求 发出的最多1.5秒内 你将会收到一个新的回调函数 而该回调函数有个古怪名字 叫didFinishRecordingLivePhotoMovie ForEventualFileAtURL. 试试分析下语法吧 它的意思是文件还没被写好 但是已经采好样了 为这部影片 换句话说 若UI中有Live Photo标记 现在最好把它去掉了 让人们知道不用再举着相机不动了 现在最好把 Live Photo标记去掉 很快地 影片文件就会被写入完成 然后你会得到didFinishProcessing LivePhotoToMovieFileAtURL. 如果你制作Live Photos 那这是必需的回调函数 现在你可以欣赏影片了
最后你竖个大拇指吧 都完成了 我们所有该做的都做完了 要注意的是拍摄 Live Photo的JPEG部分 和拍摄静态照片是一样的 它作为样例缓存保存在内存中 利用didFinishProcessingPhoto SampleBuffer这个回调函数 如我们已见过的方式 如果你想把它写到硬盘上 那可是个琐碎的活 我们在AVCapturePhotoOutput里 有一个类方法 用来把JPEG重写成Data文件 D是大写的 这个方法很适合将 JPEG文件写入硬盘中 你可以在这里的action看到 我先跳过第二个参数 也就是previewPhotoSampleBuffer 我们一会儿再讲它
在此我有个做 Live Photo的建议 拍摄Live Photo是 某一类拍摄的例子 也就是传递多种资源的拍摄 这有点像分单购物 比如你使用一个订单购买电脑 和使用另外一个订单购买适配器
所以我们发现当传递多种资源时 我们可以很便捷的 我们所写的测试应用中进行测试 来实例化一个新的 AVCapturePhotoDelegate对象 为当前场景的每个照片请求 接下来在这个对象里 你可以汇集 所有你得到的东西 面向这个请求的样本缓冲影片等等 然后有个方便的地方来处理这个对象 即thumbs up回调函数 标志着我们完成了 这是一个有用的小提示
在你的资源被写入硬盘时 你还需要做几个步骤 来获取完全的动态图片体验 尽管视频部分是 标准的QuickTime影片 但那并不意味着它可被从头到尾播放 像是用一个AVPlayer 播放普通电影那样 这里有一个可以回放它的小窍门 它应该可以在照片的 动态图像时间缓入缓出 当你在这些资源间滑动的时候 它们会在photos应用里 有些许移动 为获得完全的 Live Photo回放体验 你需要使用photos和 photos UI框架 还有与Live Photo相关的类 用来将你的RAW资源摄取到照片库中 并恰当的播放它们 例如 通过LivePhotoView
且iOS 10中新提供了 photos框架可以让你就像编辑 静态照片来编辑Live Photo 这是个很棒的消息 我想做一下演示
在此我们有一些示例代码 令人尊敬的AVCam 得有五年没有被用过了 但我们现在又重新装扮它 以便它有特定的照片模式和影片模式 这是因为只能在照片模式 使用Live Photos 你要注意的是在顶部有标记告诉你 Live Photo模式是开还是关 你还可以切换摄像头 我会试着做下那个很难的甜甜圈自拍 让我们来看看我做的成不成功 你要做的就是开始 在中间拍一下 然后结束 注意看当我在自拍的时候 是有一个live标记出现的 而这就是在运用 我之前跟你说的回调函数
好了 现在它被写入了照片库 然后 在中间的某处拍一下 不错吧 但这还不是我们所能做的全部 在iOS 9中 当你想编辑Live Photo时 你会丢失其中的影片部分 但是现在你既可以在photos应用 中本地编辑 也可以使用应用内你所提供的代码 比如这个叫做 LivePhotoEditor的小例子 它在我所包含的照片编辑扩展应用中 我可以加上简单的滤镜 或是裁剪这部影片 通过它来加上有色滤镜非常的简单 值得注意的是它并没有丢失影片 我还可以播放它 然后 在中间的某处拍一下 棒极了 你可以编辑Live Photos了
好的 现在说回AVCam 就如我所说的 它有单独的视频和照片录制模式 所以你能获得最棒的照片体验 你可以获得最棒的影片制作体验 而且它展示了恰当的live标记技术 就如我谈到的 它也向你展示了如何将其写入到资源库 该示例代码现在已经可见了 你会在我们会话的页面上找到它 它甚至都被Swift化了 如果你想了解更多关于 Live Photo编辑的内容 请在周四上午11点参加505会话 你会听到其内容
我们还支持了一个叫做 LivePhotoCaptureSuspension的特性 在这个小例子里展示了 它什么时候会有用 假如说你有一个拍照的app 能发出烦人的雾角的声音
就跟着我想象该例子的场景 它会拍照 发出烦人的雾角声 现在假如说在时间轴上 你的用户在此拍了张Live Photo 然后他们在这里发出了烦人的雾角声 接下来在声音放完后又在此 拍了另一张Live Photo
这就会产生一个问题 因为两张照片的影片部分与 烦人的雾角声重叠了 你这下同时毁了 两部Live Photos影片 你会在一张照片里听到雾角声的结尾 而在另一张听到雾角声的开头
这可不太好 因此为了应对这个问题 你可以将 isLivePhotoCaptureSuspended设为真 就在你要放烦人的雾角声之前 这会使得任何在处理过程中的 Live Photos 被强行裁减到该点 你可以同样如此处理 把isLivePhotoCaptureSuspended 设为假 这会使结尾处有一个清楚的中断 以便没有任何早于该点的内容 会在你取消暂停的时候 出现在你的影片中 一个不错的小特性
让我们谈谈设备支持 我们应该让什么设备 支持LivePhoto拍摄呢 我们在所有近年的iOS设备上支持它 有个简单的方法来记忆就是 所有具有1200万像素摄像头 设备都会支持Live Photos
接下来进入我们今天的下一个 重要特性介绍 那就是RAW相片拍摄
为了解释什么是RAW图像 我得先高度概述一下 CMOS传感器是如何工作的 CMOS传感器会采集光中的光子 通过二维阵列的传感器 数组的上层叫做颜色过滤阵列 当光线透过上层时 它只允许一种颜色通过 红 绿 蓝 其一 依照Bayer模式 绿色在这个小棋盘上 是其他两种颜色的两倍多 因为我们的眼睛 对于绿色光有着两倍的敏感度 相比于其他两种颜色来说 底层被称为传感器阵列
在RAW文件中实际存储的是强度 此强度即红 绿 蓝光的数量 穿过传感器 每个探测器 也需要被存储在Bayer模式中 换句话说 就是红 绿 蓝光的排列 以便之后将其去马赛克化 你还要存许多其他元数据 像是颜色信息 曝光信息
因此RAW转换器工作很繁重 RAW会提取所有这些东西 并将其转换为RGB图像
去马赛克化只不过是冰山一角 在其被最终呈现在屏幕上之前 有许多工作需要完成
如果做个类比的话 存储RAW文件很大程度上就像是 存储用来烤蛋糕的原料 然后你走到哪都得带着这些原料 这样可太重了 也太糟糕了 每次你都要花些时间来烘烤它 如果你让两个不同的烘焙师 用相同的原料来烤蛋糕 你或许会得到口味有些许不同的蛋糕
但是使用RAW也有一些很大的好处
首先最重要的是 你可以灵活掌握烘焙的时间 你是把原料都在身边 但你可以来年再做一个更好的蛋糕
这里不会有像是BGRA或者420 那样的压缩出现 你有更多的比特可供操作 有一个10比特的RAW传感器 包括在每像素14比特而不是8比特
另外你有很多的净空间可供编辑
而且还给予你 创作空间来做出不同的决定 其实你就是把烘焙时间往后拖 那么JPEG又是什么呢 RAW图像提供了很多优势 但它们不是最终的存在形式 重要的是你要清楚你选择RAW时 是要有所取舍的 JPEG仍然是一个有吸引力的选项
JPEG就像是 专为你烘焙的Apple蛋糕
这是个不错的蛋糕 它包含着Apple的所有善意
快得多的渲染速度 你就不必再带着这么多原料了
你还会获得像是防抖那样的好东西 就如我之前提到的 我们使用多张图片融合来进行防抖 你用一单张 RAW照片是得不到的 不管它质量多好也不行 因为我们是要拍 我觉得就有点像是多层的蛋糕 所以你用单张的图片是做不到的 而且你也获得了更小的文件尺寸
因此所有这些东西使得JPEG 变成非常有吸引力的替代方案 你得决定你想要用哪一个 才对你的应用来说更好 我们用四个字符的编码 来识别RAW格式 如我们在Core Video框架中 识别普通像素格式那样 在CVPixelBuffer.h中 加入了四个新的常量 用来描述四种不同的Bayer样式 你会在相机应用中遇到的 它们被列在这 它们基本上是描述了 红 绿 蓝光在棋盘上的顺序
你怎么用AVCapturePhotoOutput 来拍摄RAW呢 其实挺简单的 RAW仅在使用相片格式时才被支持 也就是预设的照片 跟Live Photo一样 而且它只支持后置摄像头
我们支持RAW的包围曝光 所以你可以拍摄包围曝光 例如 给三张RAW照片
为了请求一个RAW拍摄 你要创建一个 AVCapturePhotoSettings对象 但是神奇吧 这里有个不同的结构体 该结构体接收 rawPixelFormat 那你怎么决定应该 让它生成哪种RAW格式呢 你可以问下PhotoOutput 它会告诉你我有RAW相片像素格式 你可以从中选择一个
你声明的RAW格式 必须要被硬件所支持 还有一个重要的事 是在这些RAW设置当中 SIS是没有意义的 因为这不是一个多图片融合的场景 因此autoStillImage StabilizationEnabled 需要被设为no 否则会抛出异常 highResolutionPhotoEnabled也是 毫无意义的 因为你只是要获得RAW的功能 所以它也要被设为false
有一个关于RAW照片的 单独委托回调函数 叫做didFinishProcessing RAWPhotoSampleBuffer 你非常才思敏捷的话 你就会注意到它有着完全相同的参数 就和你之前获得 常规照片时的回调函数一样 didFinishProcessing RAWPhotoSampleBuffer这个回调函数 现在你可能想问 我们为何还这么麻烦给RAW样本缓冲 弄一个新的委托回调函数呢 既然它和另一个有着完全相同的参数 其实有一个很好的理由 这个理由就是
为了支持RAW plus processed图片 我们支持该种照片 就像DSLR相机 无反光板相机那样 这是种能让你同时得到RAW和JPEG 的工作流 即processed图片的意思 能同时拍摄RAW和JPEG 可是相当专业的特性
你能获得RAW plus processed图片 它不是必须得是JPEG 它也能是BGRA 420
processed图像 被生成到另一个回调函数 叫做didFinishProcessingPhoto SampleBuffer RAW被生成到名字当中带有 RAW的那个回调函数
RAW plus processed brackets也被支持 看看你是不是能想明白 其实就是 我要做一个包围曝光 同时我请求RAW plus JPEG 所以我做了三次包围曝光 我会得到三张RAW 和三张JPEG图片
但是其并不支持RAW plus 静态照片防抖
为了拍摄RAW plus JPEG 你还得需要另一个叫 AVCapturePhotoSettings的结构体 在这个结构体中 你要声明RAW像素格式 还有你想要的processed格式 在此我选择了JPEG和 RAW作为输出格式
当你选择JPEGPlusRAW时 HighResolutionPhotoEnabled 是有用的 因为它现在被应用到JPEG上
让我们讨论下如何存储 RAW缓冲 如果你在内存层面跟它们打交道的话 那它们就不那么有用了 所以与其介绍 一个Apple专利的RAW文件格式 就像许多其他相机供应商做的那样 不如选使用Adobe的 数字式负格式来存储 DNG是一个标准化的方式来 储存比特和元数据 它并不是指一种文件格式 回到我们的烤蛋糕类比 DNG就像是存原料的盒子 还是取决于个体的RAW转换器 来决定怎么解释那些原料 因此由第三方应用所打开的DNG 可能看起来不太一样 与另一个应用打开的DNG相比
所以存储DNG是相当琐碎麻烦的 你要调用一个叫做 dngPhotoDataRepresentation的类函数 把你从委托回调函数中 获得的RAW缓冲传出去 这会在内存中生成 一个可被写入文件的Data 并且这个API会写入很多的 压缩DNG文件 来保存空间
这里该有个演示了
对于RAW拍摄 我们更新了另一部分的令人尊敬的代码 叫做AVCamManual 我们是2014年发布的 在我们展示手动控制API时 它让你选择对焦 曝光 白平衡 你可以手动或自动控制这些功能 在左边的HUD里有个新东西 可以让你选择开或者关RAW 你可以选择在该应用里拍摄RAW照片 让我们看看曝光吧 我看看能不能故意过曝一点
然后我再拍张照
现在我要退出这个应用 我要打开一个叫 RAWExpose的应用 这个应用不是 AV Foundation团队写的 而是Core Image团队写的 他们很有风度的把它借给我来做演示
我们来看下刚刚拍的照片 这是张RAW照片 它会读取DNG文件 我们可以做到用 JPEG永远都做不到的事 像是我们可以恢复EV值 还能调整色温和色调 所有这些都是在后期完成的 而且完全可逆 我也可以看看有或没有 减少噪点看着是什么样的 这就是编辑RAW的 新Core image API的部分特性 我们再回到幻灯片中
AVCamManual的 示例代码现在可见了 你可以找得到 它和这节课的幻灯片是有关联的 如果你想学到 更多关于RAW编辑的内容 你可以去我刚才提过的同个会话 505会话 他们会同时谈到这两点 第二个部分是通过 Core Image来处理RAW 这是个不错的部分
RAW照片拍摄都被什么设备支持呢
巧合的是 和我们Live Photos 支持的设备一样 所有具有1200万像素摄像头的设备 都支持RAW照片拍摄
我们的下一个话题是 拍摄预览图像 也就是缩略图
摄影app通常会拍照 然后想快速显示预览结果 像是Apple Zone相机应用 当照片播放时注意看下左底角
你一按下快门键 几乎同时就有一张照片预览 出现在左底角 这会令你的用户感到欣慰 知道他们拍的照片没问题
这会给他们即时反馈
有许多的图像处理算法 像是Core Images CIRectangleDetector 或是CIQRCodeDetector 能很好兼容小图像 或是未压缩的小图像 它们不需要整张1200万像素的 JPEG来找到人的脸
不幸的是 这里有个继承阻抗的不匹配 你请求一张高质量的JPEG图片 因为你想要将其保存在硬盘上 那是你想要留下来的 但是你也想要很快在屏幕上 显示一个预览图 所以如果你要自己实现的话 你要解压缩JPEG 你要缩减它的大小 并最终显示出来 这些都需要费时占空间 还增加了复杂度 最好是能同时得到 供保存的高质量JPEG图片 以及相机能提供一个小版本的照片 直接从相机获取 而不是从JPEG解压缩而来
然后你就能省略那些步骤 直接显示预览图了 我们在AVCapturePhotoOutput中 就提供了这种工作流 这个委托
我强烈建议用啊 这个委托回调函数能生成一个缩略图 给processed或者RAW照片 预览图是非压缩的 因此你可选择它是 420fv还是BGRA格式 如果你知道想要的尺寸 你可以声明你想要的具体大小 如果你不确定对于当前的平台 多大的预览图合适的话 PhotoOutput可以为你 选择一个合适的默认尺寸
这里有些如何请求预览图的示例代码 当以常规方式创建了 一个相片设置实例后 你可以选择 previewPixelType 再说明一下相片设置本身 就会告诉你哪些格式是可用的 并且它们都是排好序的 因此最优选择会排在第一位 在此我从数组中获取第一个元素 我所说的最优是指 需要从本地相机请求最少转换的
你利用该格式类型key来创建 CVPixelBuffer属性字典 第一部分是必需的 如果你想获得预览图 那你至少你得声明你想获得什么格式的 你还可以选择性的声明宽度和高度
如果你想要定制尺寸的话 你不需要知道明确的宽高比 关于你将获得的图片 我在这设成是160乘160 我不是想搞一个盒子出来 我只是给宽和高设一个最大值 AVCapturePhotoOutput 会进行改变大小的工作 为预览图 以便它能以预设的宽高比装进盒中
获取预览图也是非常直观的 我们在此请求一个JPEG照片 还有一个160乘160的预览图
当我们获得第一个回调函数 说明已经接到命令时 你会获得一个willBegin CaptureForResolvedSettings
和一个ResolvedPhotoSettings对象 如果你注意到的话 预览图的大小不是160乘160 而是160乘120的 因为它已经因宽高比而改变 这个尺寸对于1200万像素 的照片是最合适的
当didFinishProcessingPhoto SampleBuffer回调函数最后到来时 你会得到一个 而不是两张照片 全尺寸的JPEG文件是第一个参数 previewPhotoSampleBuffer 是第二个 如果你一直跟着我的思路 并在你的脑中思考 如果你要拍一个 RAW照片 加上包围曝光 加上JPEG 加上预览图 那么你会得到mRAWs mJPEGs和mpreview照片
另一个预览图的好的应用是 作为嵌入的缩略图 在你的高质量JPEG或DNG文件中 在这段代码示例中 我会用 previewPhotoSampleBuffer这个参数 此参数在didFinishProcessingRAW PhotoSampleBuffer回调函数中 作为放到DNG文件的嵌入式缩略图 当我调用PhotoOutput的 dngPhotoDataRepresentation时 我会将其作为第二个参数传递 你一直要这么做 嵌入一个缩略图是个不错的主意 因为你不知道它会从哪被观看
有些应用能观看DNG bits RAW bits 有些则不能 但是如果你用到嵌入式缩略图的话 谁都能看到点什么 你绝对想这么做 若你添加一DNG文件 到照片库 以便获得更好的快速预览效果的话
预览图生成是被支持的 到处都是
今天的最后一个主题是 宽色域 如你所料 这是个很广泛的主题
你们肯定听说了那漂亮的真彩显示 在我们的9.7寸iPad Pro上 它是宽色域显示的 和4K 5K iMax处于同一水平 它可以显示出令人吃惊 栩栩如生的红色和黄色 以及非常深度饱和的青色和绿色
为了利用到显示的宽色域 我们在iOS9.3中 首次介绍了颜色管理 我不知道你是否注意到了 我们在9.7寸iPad Pro上 使用了颜色管理 既然显示效果这么棒了 用同样的宽色域来拍照才说得过去 以便增强我们的观看体验 另外还能保证 从现在起若干年后你再看这些照片 你会得到更多的颜色信息 从iOS10开始 9.7寸iPad Pro上 拍照会自动变成宽色域了
让我简单介绍下宽色域是什么意思 有关宽色域的术语 从颜色空间的概念开始 一个颜色空间描述的是
一个颜色的环境 颜色被呈现 排列 比较 或计算 在计算机显示中应用最普遍的颜色空间 就是sRGB s代表标准 就是标准RGB 它是基于一个国际规范ITU709 它有大概2.2的gamma值 6500开尔文的白度 sRGB对显示很多常见颜色都很出色 像是面部 天空 草地等等 但也有很多颜色sRGB不能很好生成
例如 超过百分之40的职业足球队服 超出了sRGB的色域 谁知道呢
9.7寸iPad Pro支持宽色域 并使用了一个新的颜色空间 我们将其称为Display P3
它与SMPTE标准DCI P3类似 那是用在数字影院投影仪上的颜色空间 其色原与DCI P3是相同的 但是其gamma值和白度不同
它的gamma值与 白度和sRGB是相同的
我们为什么会这么做呢 是因为DCI P3的白度 是向绿色边倾斜的
选择这么做是为了给昏暗的 家庭影院场景提供最大的亮度 我们发现把白度设为6500的话 会得到与sRGB标准会兼容的超集 在这张幻灯片上你会发现 sRGB的灰色 然后你会发现 贴附的Display P3 它尽可能宽的覆盖了sRGB的超集 这就是为何我们选择它
如果使用OS 10上的 颜色同步工具的话 你就能看到Display P3的 虚拟呈现 我截了一些图来展示给你们
你们可以在三维将其与 sRGB进行比较 在此我选择Display P3 点击“作比较” 这是个不错的技术 然后我选择sRGB 接下来我会看到 其中一个贴附在另一个上 你会从里面看到sRGB 从外面看到Display P3 以此你能感受到Display P3 相比sRGB来说有多宽 并且能呈现的 颜色范围从视觉上看也更大
那么现在让我们看看所有的细节 用来获得Display P3内容 为了获得高保真度 所捕捉内容的颜色空间 需要在素材阶段就确定下来 这可不能向下在sRGB中完成了 然后再往上向宽色域转换 它必须在开始时就被设定好足够的宽度 如你所料 颜色空间其实就是 AVCaptureDevice 一个属性 因此我们会花些时间来讨论下 AVCaptureDevice 我们还会讨论下 AVCaptureSession 该会话就是 自动宽色域选择被决定的地方 为整个会话配置
AVCaptureDevice就是AV Foundation 如何呈现摄像头或是麦克风 每个AVCaptureDevice 都有一个格式属性
Formats是AVCaptureDevice 格式的一个数组 它们本身就是对象 同时它们还会代表设备捕捉内容的格式 如你所见 它们是成对出现的 对于每个分辨率和帧率 都有一个402v版本和402f版本 v是代表视频范围 从16到235 f是代表全范围 从0到255
iOS10中新出现的是 AVCaptureDevice格式 有了一个新支持的颜色空间属性 它是由数字组成的数组 0是代表sRGB 而1是代表P3 D65
我们将其代指为Display P3 但是在API中 它指的是P3 D65 d代表显示 65代表开尔文的白度
在9.7寸iPad Pro上 420v格式只支持sRGB 但是全范围420f格式支持sRGB 或是Display P3 该设备有个可设的格式属性 这不是新的东西 列表中的其中一个格式 一直是activeFormat 如你所见 我将激活的格式套上了一个黄色的格子 它正好是1200万像素 30FPS的版本
如果那个activeFormat 也就是f格式 正好支持Display P3的话 那么你可以设置一个叫做 activeColorSpace的新属性 如果activeFormat支持它 你就能从你的素材中获得宽色域的流 到session的所有输出中
这段说起来有点冗长 但我希望你记住的是 希望这些东西你一个也用不上 大多数客户从来不需要直接设置 activeColorSpace 那是因为AVCaptureSession 会试着为你自动完成
在iOS 10中 AVCaptureSession有一个长的新属性 叫做automaticallyConfigures CaptureDeviceForWideColor 它什么时候会为你选择宽色域呢
在iOS 10中 宽色域仅在摄影中使用 让我再说一遍 在iOS 10中 宽色域仅在 摄影中使用而不是摄像 我后面马上会解释为什么
会话会自动选择 是否为整个会话配置宽色域 它会代表你将你设备的 activeColorSpace设为 P3 这取决于你的设置 你要在你的会话中 加入一个PhotoOutput 如果你没有PhotoOutput 你就不能拍照了 那么你也不需宽色域
这里有些警示 如果你开始往你的会话加入其它输出 或许你想要做什么就不那么明显了 如果你加上了一个 AVCaptureVideoPreviewLayer 会话还是会给你 自动挑选Display P3 因为你就是在拍照同时做了预览 如果你有一个MovieFileOutput 和一个PhotoOutput 那就模糊了 你可能更关心影片 所以它就不会为你 自动挑选Display P3了 VideoDataOutput是个特殊的例子 我们通过一个回调函数将缓冲送达给你 在此session只会挑选 Display P3 如果你在用预设照片的话 它很确信如果你正在用 VideoDataOutput 就意味着你会利用这些显示缓冲来摄影
如果你非常想要的话 你可以强制拍照设备 来使用宽色域 下面是怎么实现的 首先你要告诉会话 不要自动帮我实现了 不要妨碍我
然后你要进入设备 自己将activeFormat 设为支持宽色域的格式 然后你要将 activeColorSpace设为P3
你做完了之后 宽色域buffer会流到 所有接受视频数据的输出 包括VideoDataOutput MovieFileOutput 甚至是已经不推荐使用的 AVCaptureStillImageOutput
当你强制将设备的 activeColorSpace设为display P3后 我强烈建议你不要这么做 除非你明确知道自己在干什么
因为宽色域是给照片服务的 我们对于宽色域的照片支持 有着良好的生态系统 但是对于视频就不怎么样了 对于Display P3 内容的主要担忧 就在于用户必须是宽色域敏感的 否则你的内容将会以sRGB渲染 颜色看起来就会不对头 它们被渲染得很糟糕 大多数视频播放服务都不是色敏感的 所以如果你保存一个 宽Display P3影片的话 然后你试图用某个服务来播放它 它很有可能会把颜色渲染错误
如果你选择这么做 确保你的VideoDataOutput 是色敏感的 它要传播颜色标签 它要是色敏感的
如果你选择用MovieFileOutput 来拍摄Display P3影片 注意它们可能在其他平台上 是错误渲染的 这里 我们确实允许这么做 因为我们意识到 其对于某些专业工作流是很重要的 也要能够制作宽色域影片
所以抛开警告不管 我可以告诉你我们对于照片 有个很好的解决方案 针对共享宽色域 我们应该注意到JPEG宽色域 是使用Display P3属性的 并且这些图片的用户也必须是色敏感的 好消息是通常照片服务 目前是色敏感的 iCloud照片库就是其中之一 它能智能的将你的照片 转换成sRGB格式 如果你的设备不支持宽色域的话 但仍会在cloud上 存储宽色域的照片
我们的业界目前也在转变 有些照片服务虽然不支持宽色域 但它们中绝大多数至少能将其 智能渲染成sRGB格式
对于混合共享的场景 像是通过信息或邮件来发送照片 你不知它被发送到哪 它可能会被发到多个设备 其中有些可能支持宽色域 有些则不支持 对于这种情况 我们要加上一个新的服务 叫做 Apple Wide Color Sharing Profile 你的内容将以一种方式被处理 我们会生成一个内容为准则 表格形式的ICC资料 对应那张JPEG照片 其好处就在于 如果它被某人渲染 而这个人不了解宽色域 那么在sRGB色域内的部分 肯定能被正确渲染 额外的信息会被放到 一个额外的ICC资料中 它们可以将宽色域信息恢复 到最小的质量损失程度
你可以学到更多有关 如何共享宽色域内容 在505和702会话中 它们都是在周四 第一个我已经提到三遍了 关于宽色域的那个也是个不错的会话
在9.7寸iPad Pro上 AVCapturePhotoOutput 广泛支持宽色域 它在420f BGRA和JPEG中都支持 不仅仅是420v 如果你的会话 配置了Display P3 但是然后你说你想要420v的照片 它会被转换为sRGB格式
Live Photos支持宽色域 静态和影片部分都支持 这是特殊的影片 这是Apple生态系统的一部分 因此那些都会是支持宽色域的
包围曝光拍摄也是支持宽色域的
有趣的是 我一直在说iPad Pro 我们支持RAW格式 RAW拍摄本身就是宽色域的 因为它有所有那些额外的比特信息 我们将其保存在传感器基元中 并且它也有足够的颜色信息 来被渲染成宽色域或是sRGB 再说一下 如果你随身带着原料的话 你能随时决定你是想渲染成 宽色域还是sRGB 因此拍摄RAW照片并后期渲染 可在许多iOS设备上生成宽色域内容 而不仅是在iPad Pro上
你可以学会更多有关宽色域的知识 不光是共享还有别的 最好的学习宽色域的会话是在周四下午
使用AVCapturePhotoOutput 来改善可用性
我们今天谈论了四个主要特性 我们讨论了在你的应用中 拍摄Live Photos RAW RAW + JPEG DNG
用来更快渲染的小预览图 还有宽色域照片
一个小时真的不够啊 想要涵盖要讲的内容太短了 因此我们对于这个会话做了一个补充 它已经录制完了 现在已经放到网上了 它是一个包含语音的幻灯片 我们把它叫做Chalk Talk
它为你讲述了 我们没时间讲的深入的主题 AVCapturePhotoOutput 中的场景监控 资源准备和回收 然后是一个不相关的话题 iOS 10中相机隐私政策的变动 请看下那个视频 它大概20分钟长
有着更多的信息 501结尾你要记住 你会发现那个视频 有七段示例代码 还有 AVCapturePhotoOutput的新文档 文档编写人员真的很努力工作 他们写的文档真的不错
再次提醒一下这是相关的会话 这个是Chalk Talk 关于AVCapturePhotoOutput 的延伸知识 你什么时候想看都行
好了 好好享受下之后的演说 感谢你们的到来 -
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。