大多数浏览器和
Developer App 均支持流媒体播放。
-
拍摄和处理 ProRAW 图像
如果您的 app 支持 ProRAW,通过整合标准 RAW 信息和 Apple 的高级计算摄影技术,您可以帮助拍照的人轻松拍摄和编辑图像。我们将向您简要介绍该格式,包括 ProRAW 图像的外观、使用感受、质量指标以及与您的 app 的兼容性。我们将从这里开始探索如何在制作流程的每个阶段将 ProRAW 整合到您的 app 中,包括使用 AVFoundation 拍摄图像、使用 PhotoKit 存储图像以及使用 Core Image 编辑图像。
资源
- Capture setup
- Capturing Photos in RAW and Apple ProRAW Formats
- Capturing Still and Live Photos
- Core Image
- PhotoKit
- Photos
相关视频
WWDC21
WWDC20
-
下载
♪低音音乐播放♪ ♪ 大卫海沃德:嗨 我是大卫海沃德 我是 CoreImage 团队的工程师 今天 我和我的同事托马斯维塔宁 还有马特迪克夫会详细地介绍 关于ProRAW图像格式 大家需要知道的全部内容 以及如何在你的应用程序上支持它 这些是我们今天会讨论的内容 首先 我会描述ProRAW文件 是由什么构成的 接着 我们会讨论如何采集这些文件 如何把它们存到照片图库 以及如何编辑和显示它们 让我们从什么是ProRAW开始 过去一段时间 Apple装置能够 充分利用我们的图像信号处理器 来采集已经准备好要显示的 漂亮的HEIC或JPEG图像 从iOS 10开始 我们支持采集拜尔数组的 RAW传感器数据 以及将它储存在DNG文件中 这两种方式的差异和优点 在2016年WWDC的 《iOS摄影的发展》这个课程中 有很详细的介绍 那段介绍用了很棒的比喻 来描述这两种格式 处理过的HEIC或JPEG 就像是你去面包店 点了一个很多层的蛋糕 而拜尔数组RAW文件 就像是你去杂货店 采买要用来做蛋糕的原料 经处理的HEIC或JPEG的优点是 你会得到Apple烘焙好的最终图像 它能快速地显示 而且有很棒的画质 因为它是利用智慧HDR 深度融合或夜间模式 融合多个采集图像帧 所制作出来的图像 另外 因为它使用进阶有损数据压缩 所以文件尺寸比较小 拜尔RAW的优点是你会得到一个 有较大编辑弹性的图像 它没有用有损数据压缩储存 以及更多像素的精密度 我们在ProRAW上的目标 是建立一种同时具有两边 最棒的特色的图像格式 ProRAW的优点是 它和HEIC有相似的外观 不过却是使用无损数据压缩 此外 根据场景的状态 它会从多重曝光来融合 因此它在编辑时有很棒的动态范围 因为它们是低噪点和已经去马赛克 所以可以相当快速地显示 ProRAW格式是设计来最大化三项属性 兼容性、画质和外观 让我们仔细来介绍这三项属性 为了要确保兼容性 ProRAW文件是包含在一个 标准Adobe DNG文件中 Apple app 例如照片 Adobe app 例如Lightroom 还有许多其他应用程序 都支持线性DNG文件格式 许多app通过像是ImageIO 和核心图像的系统框架 能自动取得支持 iOS和macOS早期的版本 也有这个格式的基本支持 同样值得一提的是这些文件可以包含 全分辨率、JPEG画质预渲染的预览 所有通过相机app采集的ProRAW 都包含这些预览 即便是没有开启ProRAW模式下 所拍摄的 这些预览看起来也会跟图像完全一样 ProRAW文件的画质相当优秀 DNG中的像素是场景对应的 和可线性化的 可以通过多重去马赛克曝光 结合图像融合来生成 非破坏性压缩的12位元RGB 不过我们是以适应性压扩曲线 来建立这些位元 因此我们可以达到14级光圈的 动态范围 产生的文件大小可以从10兆字节 到40兆字节 这个大小 会根据每张照片独一无二的场景 而有所调整 Apple下了很多工夫 在调校我们的图像画质 ProRAW图像的默认外观 跟我们的HEIC和JPEG外观是一致的 这是通过在DNG文件中 嵌入特殊标签达成的 这些标签是记载在DNG规格中 并且提供如何渲染每张图像的 预设外观的制作方法 第一个用到的标签是 LinearizationTable 它能将12位元储存的数据 解压扩成线性场景值 我们使用BaselineExposure标签 因为ProRAW图像会配合场景的 动态范围 BaselineSharpness标签 能让我们指定 预设的边缘锐化应该用多少 在DNG 1.6规格中的新标签 ProfileGainTableMap 让我们描述 如何调整亮区和阴影区 最后一个是ProfileToneCurve 它会指定输出的全局色调曲线 这些标签对每张图像都是独一无二的 因为它们提供的是配方而不是蛋糕 图像保有高度的可编辑性 举例来说 你随时都能更改 默认的锐利度或是色调曲线 最后 当物体显示在场景中时 我们在ProRAW中的某些区域 储存语意遮罩 像是人物、皮肤和天空 现在我们知道ProRAW是由什么构成的 我要把时间交给托马斯 他会告诉大家如何采集它们 托马斯维塔宁:谢谢你 大卫 我是托马斯维塔宁 我是相机软件团队的工程师 我会带领大家认识 如何使用你的应用程序 来采集Apple ProRAW AVFoundation采集API 让你能存取iOS和MacOS上的相机 它们让你可以串流实况预览和视频 其他还有采集照片 和录制影片 在最近增加的内容中 我们新增支持 以Apple ProRAW DNG格式采集照片 关于AVFoundation采集API基本使用 有个很棒的数据源是 2016年WWDC的演讲 《iOS摄影的发展》 解释了如何使用AVCapture照片输出 以及AVCam范例编码 那是一个 简单相机采集应用程序的范例 接下来 我们会仔细来看看 Apple ProRAW采集 不过 让我们先快速看一下 哪些装置支持Apple ProRAW 一个好的起始点是 和现有的拜尔RAW支持互相比较 拜尔RAW是在iOS 10导入的 在很多种装置上都支持这个格式 Apple ProRAW则是在iOS 14.3导入的 iPhone 12 Pro和iPhone 12 Pro Max 能支持这种格式 Apple自己的相机应用程序 支持Apple ProRAW采集 和所有的融合采集 例如深度融合 和夜间模式 以及用闪光灯采集 Apple ProRAW能将照片画质优先排序 设定为.balanced和.quality 这能让你在你的RAW采集上 获得Apple图像融合的好处 单镜头AVCaptureDevices 像是广角或长镜头 只支持拜尔RAW 而所有装置都支持Apple ProRAW 包含双广角、双镜头、三镜头装置 而且在变焦时 可以流畅地在镜头之间转换 和拜尔RAW一样 Apple ProRAW不支持深度数据传输 也不支持内容感知变形校正 只有拜尔RAW支持实况照片采集 不过人像效果遮罩和语意分割 皮肤和天空遮罩只能用ProRAW 让我们来看看大家要如何 采集Apple ProRAW 我们会讲到的项目有 如何设置你的采集装置和采集对话 如何设定你的照片输出 如何准备你的照片设定 来使用ProRAW采集 以及在你采集ProRAW照片后 有哪些选择 让我们从设定对话开始 只有支持最高画质照片的格式 能支持Apple ProRAW 你可以通过将采集sessionPreset 设定成.photo来做到这件事 或者你想要手动选择装置格式 你可以去找支持最高画质 静态照片的格式 注意到这和高画质静态照片不同 那种是很多格式都支持的文件 接着 只要将想要的格式 配置成装置的activeFormat 在这个例子和后面的内容中 我会直接用支持项目的 列表中的第一个标志 不过你们会想要把它换成 在最适合你的应用程序使用 这个标准下的选项 现在让我们来看看如何替ProRAW采集 配置照片输出 首先 你需要在photoOutput上 启用ProRAW 一定要在开始对话前先做这件事 否则它会导致 漫长的管道重新组态 将这个属性设定为真 替ProRAW采集准备好 采集管道 然后将ProRAW像素格式 加到支持的RAW照片像素格式 类型清单中 你想要的话 也可以指示采集管道 你希望在你的采集中 是速度还是画质优先 或者你希望是这两者平衡的采集 关于照片画质优先排序 对于采集照片的影响的更多信息 可以去看《以影片格式 采集高画质照片》的演讲 接下来 我们会看看大家 该如何做采集的准备 要建立能使用ProRAW采集的 照片设定 你需要选择正确的RAW像素格式 你可以从同样支持拜尔RAW格式的 availableRawPhoto PixelFormatTypes 得到支持的RAW像素格式 你可以利用photoOutput上 新的isAppleProRAWPixelFormat 类别方法 从拜尔RAW格式中 区分出ProRAW格式 ProRAW像素格式的一个范例是l64r 那是一个16位元全范围RGBA像素格式 做为参考 你也可以用 isBayerRAWPixielFormat类别方法 来查询某个格式是不是拜尔RAW格式 接着 我们会讨论一些你可以用来 采集Apple ProRAW的选项 也可以是伴随一张 完全渲染处理的照片 要采集ProRAW的 第一个也是最简单的选项 就是只请求ProRAW照片 你可以在建立photoSettings时 直接指定rawPixelFormatType 来做这件事 这会产生单一资产 让你可以 很轻易地处理和储存到照片图库 待会马特会示范这部分 你也可以像在拜尔RAW那样 同时采集一组处理过的照片和ProRAW 只要在photoSettings中 同时提供processedFormat就可以 不过这样一来你需要处理多个资产 也比较难在照片图库里 追踪它们 幸运地是Apple ProRAW能支持 以全分辨率JPEG图像做为缩图 在许多案例中 这能给你前两个选项中最棒的结果 要请求缩图 你可以从availableRawEmbedded ThumbnailPhotoCodecTypes中 选择想要的格式 并且指定想要的缩图维度 现在 大家快要准备好 来采集ProRAW照片了 但是在那之前 如果你想要的话 你可以针对这次采集 指定照片画质优先排序 注意到这里你指定的值 一定要小于或等于 你之前在photoOutput上指定的 maxPhotoQualityPrioritization 如果你希望客户在采集后 可以马上看到一些内容 你也能请求显示屏幕尺寸的预览图像 接着你可以用 跟所有其他静态照片采集 相同的capturePhoto方法 来采集ProRAW照片 现在 静态照片采集完成了 让我们来看看当请求的照片 准备好的时候 你可以做什么 当照片完全处理好了 代表ProRAW照片的AVCapturePhoto 会唤起你的 didFinishProcessingPhoto委托 如果你请求了采集的预览图像 现在你会得到像素缓冲 和未压缩的预览图像 或者它的CGImage表现 来显示在屏幕上 假设你同时请求处理过的照片 和ProRAW 你的didFinishProcessingPhoto 委托会被唤起两次 你可以用收到的AVCapturePhoto上的 isRawPhoto属性 来分辨ProRAW和处理过的照片 然后你可以请求ProRAW的 fileDataRepresentation 来将DNG存到照片图库中 或者也可以取得有RAW像素数据的 像素缓冲 如果你偏好用那个 像大卫刚刚说过的 ProRAW DNG会包含语意分割遮罩 包含这些遮罩是自动的 以及场景依赖式的 当AVFoundation采集API 目前无法使用遮罩的时候 你可以通过CoreImage和ImageIO API 来取得它们 这部分待会大卫会示范给你们看 最后 我们会看一些 ProRAW DNG的自定义选项 你可以通过实作 AVCapturePhotoFileData RepresentationCustomizer委托方法 来自定义ProRAW 通过实作 replacementAppleProRAW CompressionSettings 你可以改变ProRAW照片的 压缩位元深度和画质 Apple ProRAW是以有压扩曲线的 12位元 默认写入的非破坏性编码 你可以通过将画质水平维持在1 和以定制器提供想要的位元深度 来改变非破坏性压缩的 ProRAW的位元深度 这可以省下储存空间 不过依然保有ProRAW照片的高画质 要是你偏好有损数据压缩 你可以将画质水平设为低于1 这样一来ProRAW就会自动 以8位元有损数据压缩来压缩 这会让你的文件尺寸比较小 不过这样确实会对ProRAW照片画质 产生显著的影响 既然你已经实作定制器 你可以在你的 didFinishProcessingPhoto委托中 针对采集的ProRAW DNG 提出自定义的请求 通过建立定制器并且将它提供给 fileDataRepresentation 你会拿回具有你刚刚提供的压缩设定 自定义的ProRAW 这些就是以AVFoundation采集API 进行Apple ProRAW采集的介绍 我要把时间交给马特 他会向大家多说一些 关于Apple ProRAW和照片图库的内容 马特? 马特迪克夫:谢谢 托马斯!哈啰! 我是马特迪克夫 我是照片团队的工程师 首先我会跟大家介绍如何 将你们刚刚采集的ProRAW文件 做为完整资产储存到照片图库中 接着 我们会一步步介绍 如何将已经在照片图库里面的 RAW取出来 PhotoKit是一对用来 和Apple平台上的照片图库 互动的框架 它最早是被导入在这些版本中 从那之后一直有改良和扩充 尤其是它支持RAW图像格式 像是Apple ProRAW 今天我只会讲到用于处理 照片图库中的RAW的特定API 如果大家在这段介绍后 对PhotoKit还有问题 我鼓励你们去看线上的开发者文档 为了要储存一个新资产 我们需要在共享PHPhotoLibrary上 进行更动 就跟储存任何资产一样 我们要做的更动 是一个PHAssetCreationRequest 我们会把我们的Apple ProRAW文件 新增到这个资产上 成为主要的.photo PHAssetResource 让我们来看看做这件事的代码 长什么样子 首先 我们在共享照片图库上 进行更动 我们会建立一个 PHAssetCreationRequest 接着把Apple ProRAW文件 新增到它上面 成为主要照片来源 就是这样! 只要在你的应用程序看到 符合的内容时 处理成功和错误就可以了 现在我们知道如何将资产 新增到照片图库 让我们来看看要如何把它们取回来 包含那些用户已经放在 他们图库中的RAW资产 我们开心要告诉大家 在iOS 15中 我们提供了一个新的 PHAssetCollectionSubtype .smartAlbumRAW 有了这个智能相册 你可以轻易取得一个集合 其中包含所有在照片图库中 具有RAW资源的资产 这个相册跟你在Apple照片app中 看到的相册是同一个 现在我们有一些包含RAW资源的 PHAssets 让我们来看看要怎么做 才能取得这些资源 首先 我们希望替PHAsset 取得所有的PHAssetResources 接着 我们会去找 两个不同类型的来源 我们前面说过的.photo 还有.alternatePhoto 我想要花一点时间来解释 .alternatePhoto是什么 有些照片图库会包含 遵循一些数码单镜头反光相机使用的 旧的RAW加上JPEG储存模式的资产 这会需要将RAW和JPEG 存成两个不同的资源 将JPEG存成照片 将RAW存成替代照片 这会导致照片图库中的文件用量增加 可移植性变差 而且经常出现让人困惑的用户体验 我们不建议将这个模式 用在Apple ProRAW上 如果你的目的是将ProRAW文件存到 照片图库中 你应该利用采集设定 将完整大小的JPEG预览嵌入文件中 现在 回到我们的资源 我们会去检查资源的 uniformTypeIdentifier 看看它是否遵守我们有兴趣的 RAW类型 最后 一旦我们有了RAW资源 我们就会用PHAssetResourceManager 来取回实际的数据 让我们来看看它的编码 首先 我们在一个资产上 重复所有PHAssetResources 寻找任何属于.photo或是 .alternatePhoto类型的内容 确认它们遵守RAW图像UTType 最后使用PHAssetResourceManager 来请求那个资源的数据 就是这样! 现在大家知道如何利用PhotoKit 从照片图库储存和取出 具有RAW资源的资产 现在我要把时间交还给大卫 他会谈谈要如何 出色地编辑和显示Apple ProRAW图像 大卫:谢谢 马特 今天演讲的最后一段内容 是关于如何使用核心图像框架 来编辑和显示ProRAW图像 我会讲一下如何从一个ProRAW文件 建立CIImage 如何应用最常见的用户调整 你要怎么关掉预设外观 来取得线性场景对应值 如何将编辑渲染成输出导向格式 例如HEIC 和最后 如何在具有 扩展动态范围屏幕的Mac上 显示ProRAW 或许可以通过 CGImageSourceCreateWithURL 和CGImageSourceCreate ThumbnailAtIndex API 来从ProRAW中得到预览图像 在iOS 15和macOS 12中 核心图像增加了新的便利API 来存取预览 在初始化CIImage的时候 通过想要的选项键 来支持取得语意分割遮罩 例如人物、皮肤和天空 这同样有一个新的、更便利的API 来存取选择性的遮罩图像 最重要的是 你的应用程序会想要取得 主要的ProRAW图像 假设你的应用程序只想显示 预设的渲染外观 你只需要从URL或数据 建立一个不可变的CIImage就可以 然而 假设你的应用程序想开启 ProRAW的完整编辑性 那就从URL建立一个CIFilter 如果你只跟那个滤波器 要它的outputImage 你就会得到一个 有预设外观的CIImage 这个API中很重要的优势是 滤波器可以轻易被修改 RAW CIFilter有几个输入 你的应用程序可以更改它们 来制造新的outputImage 基本编码模式是 替其中一个记载的键字符串 设定一个值对象 不过这个setValue forKey API 需要更新了 因此在iOS 15和macOS 12的新内容中 我们建立了一个更容易寻见 和更适合Swift的API 要使用这个新的API 建立一个CIRAWFilter实体 然后只需要把想要的属性 设定为新的值就可以 接下来 让我们谈谈 你可能会想要改变哪些属性 考虑到ProRAW图像的动态范围 其中一个要提供的重要控制是曝光 你可以把这个值设成任何整数 举例来说 把它设成正值1 让图像变成两倍亮 或是负值1 让它亮度剩一半 因为ProRAW是在 线性场景对应空间中编辑的 调整图像的白平衡会更有效 场景的中性色可以被指定成 以开尔文为单位的温度 或者是x/y色度坐标 ProRAW外观的预设锐利度 可以被调整成任何0到1之间的值 ProRAW局部色调映射的强度 可以被调整成任何0到1之间的值 局部色调映射让图像的每个区域 都能有自己优化的色调曲线 这个例子是一张ProRAW图像 当它的局部色调映射强度完全关掉… 在一半强度的时候… 和完全打开的时候 在这张图像中 局部色调曲线让暗部亮起来 并且让亮部变暗 这样就能在标准动态范围屏幕上 呈现最好的结果 接下来 让我们来讨论你的应用程序 要如何直接取得线性场景对应数据的 14级光圈 大多数用户偏好我刚刚说过那些 常用的调整 不过对某些应用案例来说 能存取线性数据是很实用的 要取得线性图像 你只需要关掉会将预设外观 套用到图像上的滤波器输入 将baselineExposure、exposureBias boost和localToneMapAmount设定为0 并且在取得outputImage前 关掉色域转换 一旦你得到linearRAWImage 你就可以将它做为其他核心图像 滤波器的输入 来执行场景对应计算 举例来说 你可以用 内建的核心图像直方图滤波器 来计算统计数据 或者你会想要渲染线性图像 来取得它的像素数据 要做这件事 你只要针对 RGBA-half-float的可变数据 建立一个CIRenderDestination 告诉渲染目的地 去使用你选择的线性colorSpace 然后让CIContext开始 渲染rawFilter的输出图像的任务 这个范例是用一张有预设外观ProRAW 和一张采集的线性场景对应图像 来做比较 线性图像看起来比较平、曝光不足 不过它依旧包含场景中完整未修剪的 14级光圈数据 这一组图像同样很清楚的说明了 输出导向图像和场景对应图像 之间的差异 在输出导向默认外观中 图像中具有最大亮度的区域 是左边的日落 不过在右边的天空区域 它的亮度是日落亮度的百分之80 尽管默认图像看起来很美 它的亮度值不代表真实的场景 在线性场景对应图像中 图像中右边天空的 最大发光强度 只有日落发光强度的百分之12 这在物理上比较合乎逻辑 这就是为什么线性场景对应图像 对图像处理和分析这么重要 在你的应用程序 改变ProRAW CIFilter属性后 你可能会想将图像储存为 输出导向格式 例如HEIC或JPEG 这里有个例子 说明如何将 rawFilter输出图像 储存到8位元深HEIC文件 有了这个API 你可以指定 要使用的输出colorSpace 不过我们建议用displayP3 也可以用选项目录 将语意遮罩储存到HEIC中 另外 因为ProRAW具备很高的精密度 你可以考虑用这个新的核心图像API 来储存到10位元深HEIC文件 到目前为止我介绍的所有调整 会产出一张色调映射和色域转换到 标准动态范围上的输出图像 通常把它缩写成“SDR” 我想要介绍的下一个主题 是如何在扩展动态范围屏幕上 以完整的亮度呈现ProRAW图像的 动态范围 许多Mac屏幕 从MacBook Pro到iMac 再到Pro Display XDR 都能以MetalKit视图呈现EDR内容 要显示一个ProRAW CIImage 我们建议使用MetalKit视图子类别 来取得最佳性能 你的MetalKit视图子类别 应该在视图中建立一个CIContext 和一个MTLCommandQueue 关于如何在MetalKit视图中 以核心图像取得最佳性能的重要细节 请回去看我们去年 针对这个主题的介绍 如果你的Mac屏幕支持EDR 那你可以把视图的colorPixelFormat 设为rgba16Float 并且把wantsExtendedDynamic RangeContent设定为真 接着 当你的视图子类别开始绘制时 将rawFilter.extended DynamicRangeAmount设为1 并且叫核心图像环境 开始一个渲染outputImage的任务 大家一定要亲自在EDR屏幕上 看过ProRAW图像 才能真正欣赏它 让我试着模拟它看起来的样子 这里显示的是一张SDR图像 而这个显示同一个 ProRAW文件在EDR中 看起来是什么样子 亮部和反射亮点 都不再受限于色调映射 所以它们会以完整的亮度呈现 我们Apple ProRAW的报告就到这里 今天我们详细介绍了 文件格式的设计和内容 以及你可以如何采集、储存 和编辑这些图像 我很期待看到大家的应用程序 如何开启这些图像的所有可能性 ♪
-
-
7:52 - Setting up device and session
// Use the .photo preset private let session = AVCaptureSession() private func configureSession() { session.beginConfiguration() session.sessionPreset = .photo //... }
-
8:03 - Setting up device and session
// Or optionally find a format that supports highest quality photos guard let format = device.formats.first(where: { $0.isHighestPhotoQualitySupported }) else { // handle failure to find a format that supports highest quality stills } do { try device.lockForConfiguration() { // ... } device.unlockForConfiguration() } catch { // handle the exception }
-
8:39 - Setting up photo output 1
// Enable ProRAW on the photo output private let photoOutput = AVCapturePhotoOutput() private func configurePhotoOutput() { photoOutput.isHighResolutionCaptureEnabled = true photoOutput.isAppleProRAWEnabled = photoOutput.isAppleProRAWSupported //... }
-
8:59 - Setting up photo output 2
// Select the desired photo quality prioritization private let photoOutput = AVCapturePhotoOutput() private func configurePhotoOutput() { photoOutput.isHighResolutionCaptureEnabled = true photoOutput.isAppleProRAWEnabled = photoOutput.isAppleProRAWSupported photoOutput.maxPhotoQualityPrioritization = .quality // or .speed .balanced //... }
-
9:26 - Prepare for ProRAW capture 1
// Find a supported ProRAW pixel format guard let proRawPixelFormat = photoOutput.availableRawPhotoPixelFormatTypes.first( where: { AVCapturePhotoOutput.isAppleProRAWPixelFormat($0) }) else { // Apple ProRAW is not supported with this device / format } // For Bayer RAW pixel format use AVCapturePhotoOutput.isBayerRAWPixelFormat()
-
10:09 - Prepare for ProRAW capture 2
// Create photo settings for ProRAW only capture let photoSettings = AVCapturePhotoSettings(rawPixelFormatType: proRawPixelFormat) // Create photo settings for processed photo + ProRAW capture guard let processedPhotoCodecType = photoOutput.availablePhotoCodecTypes.first else { // handle failure to find a processed photo codec type } let photoSettings = AVCapturePhotoSettings(rawPixelFormatType: proRawPixelFormat, processedFormat: [AVVideoCodecKey: processedPhotoCodecType])
-
10:53 - Prepare for ProRAW capture 3
// Select a supported thumbnail codec type and thumbnail dimensions guard let thumbnailPhotoCodecType = photoSettings.availableRawEmbeddedThumbnailPhotoCodecTypes.first else { // handle failure to find an available thumbnail photo codec type } let dimensions = device.activeFormat.highResolutionStillImageDimensions photoSettings.rawEmbeddedThumbnailPhotoFormat = [ AVVideoCodecKey: thumbnailPhotoCodecType, AVVideoWidthKey: dimensions.width, AVVideoHeightKey: dimensions.height]
-
11:08 - Prepare for ProRAW capture 4
// Select the desired quality prioritization for the capture photoSettings.photoQualityPrioritization = .quality // or .speed .balanced // Optionally, request a preview image if let previewPixelFormat = photoSettings.availablePreviewPhotoPixelFormatTypes.first { photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelFormat] } // Capture! photoOutput.capturePhoto(with: photoSettings, delegate: delegate)
-
11:44 - Consuming captured ProRAW 1
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { guard error == nil else { // handle failure from the photo capture } if let preview = photo.previewPixelBuffer { // photo.previewCGImageRepresentation() // display the preview } if photo.isRawPhoto { guard let proRAWFileDataRepresentation = photo.fileDataRepresentation() else { // handle failure to get ProRAW DNG file data representation } guard let proRAWPixelBuffer = photo.pixelBuffer else { // handle failure to get ProRAW pixel data } // use the file or pixel data }
-
12:52 - Consuming captured ProRAW 2
// Provide settings for lossless compression with less bits class AppleProRAWCustomizer: NSObject, AVCapturePhotoFileDataRepresentationCustomizer { func replacementAppleProRAWCompressionSettings(for photo: AVCapturePhoto, defaultSettings: [String : Any], maximumBitDepth: Int) -> [String : Any] { return [AVVideoAppleProRAWBitDepthKey: min(10, maximumBitDepth), AVVideoQualityKey: 1.00] } }
-
13:35 - Consuming captured ProRAW 3
// Provide settings for lossy compression class AppleProRAWCustomizer: NSObject, AVCapturePhotoFileDataRepresentationCustomizer { func replacementAppleProRAWCompressionSettings( for photo: AVCapturePhoto, defaultSettings: [String : Any], maximumBitDepth: Int) -> [String : Any] { return [AVVideoAppleProRAWBitDepthKey: min(8, maximumBitDepth), AVVideoQualityKey: 0.90] } }
-
13:51 - Consuming captured ProRAW 4
// Customizing the compression settings for the captured ProRAW photo func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { guard error == nil else { // handle failure from the photo capture } if photo.isRawPhoto { let customizer = AppleProRAWCustomizer() guard let customizedFileData = photo.fileDataRepresentation(with: customizer) else { // handle failure to get customized ProRAW DNG file data representation } // use the file data }
-
15:19 - Saving a ProRAW asset with PhotoKit
PHPhotoLibrary.shared().performChanges { let creationRequest = PHAssetCreationRequest.forAsset() creationRequest.addResource(with:.photo, fileURL:proRawFileURL, options:nil) } completionHandler: { success, error in // handle the success and possible error }
-
15:45 - Fetching RAW assets from the photo library
// New enum PHAssetCollectionSubtype.smartAlbumRAW PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumRAW, options: nil)
-
17:16 - Retrieving RAW resources from a PHAsset
let resources = PHAssetResource.assetResources(for: asset) for resource in resources { if (resource.type == .photo || resource.type == .alternatePhoto) { if let resourceUTType = UTType(resource.uniformTypeIdentifier) { if resourceUTType.conforms(to: UTType.rawImage) { let resourceManager = PHAssetResourceManager.default() resourceManager.requestData(for: resource, options: nil) { data in // use the data } completionHandler: { error in // handle any error } } } } }
-
18:28 - Getting CIImages from a ProRAW
// Getting the preview image let isrc = CGImageSourceCreateWithURL(url as CFURL, nil) let cgimg = CGImageSourceCreateThumbnailAtIndex(isrc!, 0, nil) return CIImage(cgImage: cgimg)
-
18:36 - Getting CIImages from a ProRAW 2 (New in iOS 15 and macOS 12)
// Getting the preview image let rawFilter = CIRAWFilter(imageURL: url) return rawFilter.previewImage
-
18:44 - Getting CIImages from a ProRAW 3
// Getting the preview image let rawFilter = CIRAWFilter(imageURL: url) return rawFilter.previewImage // Getting segmentation mattes images return CIImage(contentsOf: url, options: [.auxiliarySemanticSegmentationSkinMatte : true])
-
18:56 - Getting CIImages from a ProRAW 4
// Getting the preview image let rawFilter = CIRAWFilter(imageURL: url) return rawFilter.previewImage // Getting segmentation mattes images let rawFilter = CIRAWFilter(imageURL: url) return rawFilter.semanticSegmentationSkinMatte
-
19:09 - Getting CIImages from a ProRAW 5
// Getting the primary image return CIImage(contentsOf: url, options:nil) let rawFilter = CIFilter(imageURL: url, options:nil) return rawFilter.outputImage
-
19:31 - Applying common user adjustments
func get_adjusted_raw_image (url: URL) -> CIImage? { // Load the image let rawFilter = CIFilter(imageURL: url, options:nil) // Change one or more filter inputs rawFilter.setValue(value, forKey: CIRAWFilterOption.keyName.rawValue) // Get the adjusted image return rawFilter.outputImage }
-
19:54 - Applying common user adjustments 2
func get_adjusted_raw_image (url: URL) -> CIImage? { // Load the image let rawFilter = CIRAWFilter(imageURL: url) // Change one or more filter inputs rawFilter.property = value // Get the adjusted image return rawFilter.outputImage }
-
20:17 - Applying common user adjustments 3
// Exposure rawFilter.exposure = -1.0 // Temperature and tint rawFilter.neutralTemperature = 6500 // in °K rawFilter.neutralTint = 0.0 // Sharpness rawFilter.sharpnessAmount = 0.5 // Local tone map strength rawFilter.localToneMapAmount = 0.5
-
21:40 - Getting linear scene-referred output 1
// Turn off the filter inputs that apply the default look to the RAW rawFilter.baselineExposure = 0.0 rawFilter.shadowBias = 0.0 rawFilter.boostAmount = 0.0 rawFilter.localToneMapAmount = 0.0 rawFilter.isGamutMappingEnabled = false let linearRawImage = rawFilter.outputImage
-
22:00 - Getting linear scene-referred output 2
// Use the linear image with other filters let histogram = CIFilter.areaHistogram() histogram.inputImage = linearRawImage histogram.extent = linearRawImage.extent // Or render it to a RGBAh buffer let rd = CIRenderDestination(bitmapData: data.mutableBytes, width: imageWidth, height: imageHeight, bytesPerRow: rowBytes, format: .RGBAh) rd.colorSpace = CGColorSpace(name: CGColorSpace.extendedLinearITUR_2020) let task = context.startTask(toRender: rawFilter.outputImage, from: rect, to: rd, at: point) task.waitUntilCompleted()
-
23:54 - Saving edits to other file formats 1 (8-bit HEIC)
// Saving to 8-bit HEIC try ciContext.writeHEIFRepresentation(of: rawFilter!.outputImage!, to: theURL, format: .RGBA8, colorSpace: CGColorSpace(name: CGColorSpace.displayP3)!, options: [:])
-
24:12 - Saving edits to other file formats 2 (10-bit HEIC)
// Saving to 10-bit HEIC try ciContext.writeHEIF10Representation(of: rawFilter!.outputImage!, to: theURL, format: .RGBA8, colorSpace: CGColorSpace(name: CGColorSpace.displayP3)!, options: [:])
-
24:51 - Displaying to a Metal Kit View in EDR on Mac
class MyView : MTKView { var context: CIContext var commandQueue: MTLCommandQueue //... }
-
25:13 - Displaying to a Metal Kit View in EDR on Mac
// Create a Metal Kit View subclass class MyView : MTKView { var context: CIContext var commandQueue: MTLCommandQueue //... } // Init your Metal Kit View for EDR colorPixelFormat = MTLPixelFormat.rgba16Float if let caml = layer as? CAMetalLayer { caml.wantsExtendedDynamicRangeContent = true //... } // Ask the filter for an image designed for EDR and render it rawFilter.extendedDynamicRangeAmount = 1.0 context.startTask(toRender: rawFilter.outputImage, from: rect, to: rd, at: point)
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。