【HDR学习】苹果EDR技术洞察(二)
?
-
綜述
蘋果用 EDR 這個詞是為了跟 HDR 區(qū)分開,因為 HDR 在不同的場景可能對應著不同的理解:
而 EDR(Extended Dynamic Range)是蘋果推出的一套渲染管線技術,以支持在不同的屏幕上同時正確顯示 SDR 和 HDR 內(nèi)容。當顯示 HDR 的內(nèi)容時,EDR 并不會直接將 HDR 區(qū)域變得更亮,而是識別到 HDR 內(nèi)容后提高整體屏幕亮度的同時,降低非 HDR 區(qū)域的白點值,使得其看起來沒有那么亮。
-
EDR 的技術方案
SDR 的像素浮點數(shù)表示范圍為?[0.0, 1.0],其中 0.0 表示黑色,1.0 表示白色。在 EDR 的像素浮點數(shù)表示中,SDR 的部分映射到?[0.0, 1.0],而大于 1.0 的部分就是比 SDR 更亮的 HDR 部分。
不像其他的 HDR 格式那樣,EDR 不會做 Tone Mapping 將像素值都映射到?[0.0, 1.0]?的范圍。這就意味著在渲染時,它有一套新的機制。當渲染時,像素浮點值范圍為?[0.0, 1.0]?的 SDR 內(nèi)容是始終會正常渲染的。(1.0, EDR headroom]?范圍的 HDR 內(nèi)容也是可以渲染的。但是,超過了 EDR headroom 的部分就會被丟掉。
EDR headroom 的存在支持了亮度更高的 HDR 內(nèi)容,但是它具體是多少呢?其實,EDR headroom 是動態(tài)的,它的值受到多種因素的影響,比如:設備的顯示技術、當前的顯示亮度等等。
我們通常可以使用下面這個公式粗略估計 EDR headroom:
Headroom ≈ Display Peak / SDRPro Display XDR顯示器可手動/自動調(diào)節(jié)的最大亮度等級是500nits(用于光線好的環(huán)境),所以把它作為1.0EDR預設值,這個范圍就是SDR的范圍,EDR值=1600nits/500nits=3.2;如果昏暗環(huán)境,手動/自動把顯示器亮度調(diào)到4nits, EDR值就是1600nits/4nits=400。
-
代碼講解
1. 以首選的EDR框架CAMetalLayer為示范。首先看以下4個步驟:選擇使用EDR-》設置擴展范圍色域-》將metaLayer的像素格式調(diào)整為浮點格式,如RGBA16Float-》實際生成EDR像素
前三個步驟代碼示例如下:
有關第四個步驟,我們用ImageIO導入HDR靜態(tài)圖像內(nèi)容,并將其渲染成EDR紋理,這個過程可以概括為: 先通過HDR圖片建立CGImage-》繪制浮點bitmap-》創(chuàng)建浮點紋理-》將EDR位圖導入到texture中-》將texture渲染成EDR可用的metal管線
1)讀取HDR原圖片,保存成CGImageRef格式。
CGImageRef ,這個結構用來創(chuàng)建像素位圖,可以通過操作存儲的像素位來編輯圖片。其參數(shù)解釋如下:
sizt_t是定義的一個可移植性的單位,在64位機器中為8字節(jié),32位位4字節(jié)。 width:圖片寬度像素 height:圖片高度像素 bitsPerComponent:每個顏色的比特數(shù),例如在rgba-32模式下為8 bitsPerPixel:每個像素的總比特數(shù) bytesPerRow:每一行占用的字節(jié)數(shù),注意這里的單位是字節(jié) space:顏色空間模式,例如const CFStringRef kCGColorSpaceGenericRGB 這個函數(shù)可以返回一個顏色空間對象。 bitmapInfo:位圖像素布局,這是個枚舉 provider:數(shù)據(jù)源提供者 decode[]:解碼渲染數(shù)組 shouldInterpolate:是否抗鋸齒 intent:圖片相關參數(shù)2)繪制浮點位圖
先讀取像素位圖的寬度、高度,再根據(jù)位圖組成信息和色彩空間(之前設置過的Display-P3),調(diào)用CGBitmapContextCreate創(chuàng)建繪圖上下文(相當于一個畫布),然后調(diào)用CGContextDrawImage方法在當前上下文畫圖。
CGContextRef?(Quartz?2D繪圖的核心API是CGContextRef,該API專門用于繪制各種圖形。)
CGContextRef CGBitmapContextCreate ( void *data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef colorspace, CGBitmapInfo bitmapInfo ); /** 參數(shù): data 指向要渲染的繪制內(nèi)存的地址。這個內(nèi)存塊的大小至少是(bytesPerRow*height)個字節(jié)。使用時可填NULL或unsigned char類型的指針。 width bitmap的寬度,單位為像素 height bitmap的高度,單位為像素 bitsPerComponent 內(nèi)存中像素的每個組件的位數(shù).例如,對于32位像素格式和RGB 顏色空間,你應該將這個值設為8。 bytesPerRow bitmap的每一行在內(nèi)存所占的比特數(shù),一個像素一個byte。 colorspace bitmap上下文使用的顏色空間。 bitmapInfo 指定bitmap是否包含alpha通道,像素中alpha通道的相對位置,像素組件是整形還是浮點型等信息的字符串。 */- CGBitmapInfo講解
CGBitmapInfo由兩部分取或運算組成,一部分是指定 cpu使用的大小端模式,另一部分指定的是顏色空間中每個 bule green red alpha 的排列順序。
typedef CF_ENUM(uint32_t, CGImageByteOrderInfo) {kCGImageByteOrderMask = 0x7000,kCGImageByteOrderDefault = (0 << 12),kCGImageByteOrder16Little = (1 << 12),kCGImageByteOrder32Little = (2 << 12),kCGImageByteOrder16Big = (3 << 12),kCGImageByteOrder32Big = (4 << 12) } CG_AVAILABLE_STARTING(10.0, 2.0);typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {kCGImageAlphaNone, /* For example, RGB. */kCGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */kCGImageAlphaLast, /* For example, non-premultiplied RGBA */kCGImageAlphaFirst, /* For example, non-premultiplied ARGB */kCGImageAlphaNoneSkipLast, /* For example, RBGX. */kCGImageAlphaNoneSkipFirst, /* For example, XRGB. */kCGImageAlphaOnly /* No color data, alpha data only */ };typedef CF_OPTIONS(uint32_t, CGBitmapInfo) {kCGBitmapAlphaInfoMask = 0x1F,kCGBitmapFloatInfoMask = 0xF00, kCGBitmapFloatComponents = (1 << 8), // 浮點型表示kCGBitmapByteOrderMask = kCGImageByteOrderMask,kCGBitmapByteOrderDefault = kCGImageByteOrderDefault, // 默認kCGBitmapByteOrder16Little = kCGImageByteOrder16Little, // 16 位小端kCGBitmapByteOrder32Little = kCGImageByteOrder32Little, // 32 位小端kCGBitmapByteOrder16Big = kCGImageByteOrder16Big, // 16 位大端kCGBitmapByteOrder32Big = kCGImageByteOrder32Big // 32 位大端 } CG_AVAILABLE_STARTING(10.0, 2.0); // Big、Little 大端和小端分別 // 大端表示低字節(jié)放在高地址,高字節(jié)放在低地址 // 小端表示高字節(jié)放在高地址,低字節(jié)放在低地址顏色空間的格式 RGB肯定要連續(xù)排序,唯一可能的變化是A的存放位置,A存放位置有兩種可能:
情況一:A放在RGB之后RGBA 對應iOS的CGImageAlphaInfo為AlphaLast.
(對于32位圖像,4個字節(jié)表示一個像素,每8位表示一個顏色。)
情況二:A放在RGB前面ARGB 對應iOS的CGImageAlphaInfo為AlphaFirst
?再聯(lián)系上大小端,那么
對于情況一:A放在RGB之后RGBA?
對于大端對齊的cpu其像素存儲格式是 0xRGBA?
對于小端對齊的cpu其像素存儲格式是 0xABGR
對于情況二:A放在RGB前面ARGB
對于大端對齊的cpu其像素存儲格式是 0xARGB
對于小端對齊的cpu其像素存儲格式是 0xBGRA
另外:Alpha通道的作用
?IOS是小端序,所以kCGBitmapByteOrder16Host就是?kCGBitmapByteOrder16Little。
3)創(chuàng)建RGBA16Float類型的紋理對象(MTLTexture)
通過newTextureWithDescriptor方法使用一塊新的用于存放texture image data的內(nèi)存來創(chuàng)建 MTLTexture紋理對象,該api中通過 MTLTextureDescriptor 來描述texture的屬性
創(chuàng)建 MTLTexture的時候 MTLTextureDescriptor 被用于定義屬性,包括圖像尺寸(寬、高、深度)、pixel format、arrangement(array、cubemap)以及mipmap的數(shù)量。MTLTextureDescriptor 值在創(chuàng)建 MTLTexture 的時候有用,當創(chuàng)建完畢后, 改變 MTLTextureDescriptor 的屬性將對已經(jīng)創(chuàng)建的 texture 沒有任何影響。也就是說,當紋理對象創(chuàng)建完成后,它的大多數(shù)屬性,比如大小,新類型,像素格式都是不能改變的,但是紋理的像素數(shù)據(jù)是可以改變。
- 創(chuàng)建一個包含 texture 屬性的 MTLTextureDescriptor :
- textureType 表示 texture的dimensionality 和 arrangement(array or cube)
- width、height、depth用于表明 texture base level mipmap中每一個dimension的pixel size
- pixelFormat表明 texture中的像素存儲方式
- arrayLength 表明 MTLTextureType1DArray or MTLTextureType2DArray 類型 texture的數(shù)組元素的數(shù)量
- mipmapLevelCount 表明texture mipmap的數(shù)量
- sampleCount 表明每個pixel的對應的sample數(shù)量
- resourceOptions 表明內(nèi)存分配的方式
- 通過 MTLDevice 的 newTextureWithDescriptor: 方法根據(jù) MTLTextureDescriptor 創(chuàng)建一個texture。創(chuàng)建完畢后,如果要復制內(nèi)存的像素數(shù)據(jù)到紋理中,調(diào)用 replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:?方法來加載texture image data
?4)將EDR的像素數(shù)據(jù)加到紋理中。
利用CGBitmapContextGetData獲取EDR圖像數(shù)據(jù),并用replaceRegion設置EDR紋理。
5)使用metal管線渲染EDR
?【相關鏈接】
bilibili講解的文字版描述:?WWDC 2022 音視頻相關 Session 概覽(EDR 相關)丨音視頻工程示例 - 掘金
bilibili講解:【中文字幕】Apple:EDR是如何工作的?HDR渲染之道 | Explore HDR rendering with EDR_嗶哩嗶哩_bilibili
w3講解EDR:http://3ms.huawei.com/hi/group/1004055/wiki_6221842.html
Apple’s “EDR” Brings High Dynamic Range to Non-HDR Displays — Prolost
微信公眾號講解:?https://mp.weixin.qq.com/s/EgJkGimBs5AF1n3O4KqYog
總結
以上是生活随笔為你收集整理的【HDR学习】苹果EDR技术洞察(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试工作的感想怎么写,软件测试工作中
- 下一篇: 广东技术师范大学一行来访虹科并进行“见习