Instagram 如何在新 iPhone 的廣色域屏幕中顯示廣色域圖像
簡評:去年九月,蘋果發布了 iPhone 7 和 iPhone 7 plus,在新品上搭配了能顯示更寬色彩範圍的 Wide Color 廣色域屏幕。Instagram 團隊剛剛完成廣色域屏幕的適配,這篇文章將分享應用程序轉換適配的過程,以幫助其他開發者也能做到同樣的事情。精準的顏色顯示意味著我們能看到最真實的色彩,設計師或許只需要關注屏幕的色彩校準,而開發者更應該關注代碼的底層實現,尤其是圖片類應用程序的開發者。
為什麼選用廣色域
在此之前,大多數捕獲的照片都是 sRGB 色域。由於 sRGB 色域與大多數顯示器能很好地兼容,因此它也成為網路上共享圖像的標準。雖然 sRGB 在大多數時候都能很好地表現顯示器的色彩,但是隨著顯示器和相機技術的提高,sRGB 開始顯現它的不足。
先看下圖這張照片,
當使用 iPhone 7 Plus 拍攝時,房間中大多數色塊都在 sRGB 色域之外,除非採用更寬的色彩空間,否則會造成細節丟失。蘋果為其新 iPhone 選擇的色彩空間是 P3,下圖中以藍色顯示的部分是在 sRGB 顯示範圍之外但是是存在於 P3 以內的:
接下來我們將介紹在 Instagram 代碼中會改變的內容,以便為廣色域提供顏色支持。A Canary
在處理廣域色彩兼容性時最有用的工具是「金絲雀圖像(Canary)」。這種圖像只有在廣域色彩範圍時才會顯示。這裡是我們的示例。
如果你看到的只是一個紅色方塊,那說明你的顯示器只能顯示 sRGB 色域。如果在廣域顯示器上打開,你會看到 Instagram logo 的出現。所以這就是一種圖像信息丟失。
你可以使用它來確定在哪個過程中你的應用程序丟失了顏色信息。
捕獲
這是比較簡單的部分。從 iOS10 開始,Apple 的 API 將從兼容的相機中輸出廣色域圖像。我們做的一個調整是轉換為新的 AVCaptureDeviceDiscoverySession,這讓我們能充分利用 iPhone 7 Plus 的雙鏡頭系統。
Core Graphics 操作
獲取圖像後,會做些簡單處理。其中大部分都是在做 Core Graphics,所以有一些變化以適配廣色域。
如果你曾經做過 Core Graphics,你可能知道這個:
UIGraphicsBeginImageContextWithOptions(...)n//你的繪圖操作這裡nUIImage * image = UIGraphicsGetImageFromCurrentImageContext(); nUIGraphicsEndImageContext();n
作為一個傳統的API,它不是廣色域的。因此,我們將採用這個:UIGraphicsImageRenderer:
UIGraphicsImageRendererFormat * format = [[UIGraphicsImageRendererFormat alloc] init]; nformat.prefersExtendedRange = YES; nUIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size format:format]; nUIImage * image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * rendererContext){ n //這裡的繪圖操作n}];n
我們為了簡化 IG 的轉換,做的是創建一個包裝類 UIGraphicsImageRenderer,它接受一個 CGContext 的圖像繪製操作。工程師可以使用 [UIImage renderedImageWithSize:(CGSize) actions:(ImageActionsBlock)actions],而 ImageActionsBlock 單個參數是一個 CGContextRef。在 iOS10 上它使用新的渲染器,調用 imageWithActions。
創建色彩空間
在其他地方,通常 CGColorSpaceCreateDeviceRGB 在創建時使用 CGColorSpaceRef。這將在大多數設備上創建 sRGB 顏色空間,我們會失去 sRGB 以外的色彩。
我們可以先看看設備屏幕是否支持廣色域顯示(使用UIScreen.mainScreen.traitCollection.displayGamut),如果是,請使用CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3)。
當我們下載圖片但不確定要使用什麼顏色空間時,我們改用它 CGImageGetColorSpace,因此,一旦我們向 iOS 應用程序提供顯示 P3 圖片,我們只在需要時創建廣色域的信息。
濾鏡
Instagram 使用 OpenGL 進行圖像編輯。OpenGL 不是顏色管理;它在一個範圍(例如,0.0 到 1.0)上操作,並且它決定映射的顏色。適配的過程中,最大的變化是確保當我們從 GL 表面提取像素緩衝區時,我們使用適當的顏色空間,然後從 a CVPixelBufferRef 轉換為 a CGImageRef。
圖像輸出
在這一點上,我們捕獲了一個廣色域圖像,在 CoreGraphics 中調整它的大小,並把它通過 OpenGL,保持廣色域的顏色信息。最後一步是用 UIImage 把它變成 JPEG。可以用 UIImages 在 Photoshop 中載入導出的圖像(Xcode 的調試器集成,以便在預覽中打開),並檢查生成的圖像的顏色配置文件和其他顏色信息。
圖像存儲
一旦圖像生成,我們做一些最後的調整,然後在 Python 使用 Pillow。最後通過 Facebook 的 CDN 在全球提供圖像。
現在的問題在於大多數用戶目前的設備都不是兼容廣色域的,因此這些設備也沒有良好的顏色管理。所以在多個顏色配置文件之間轉換圖像會增加我們的複雜性。
為了保持簡單,我們選擇了在後端存儲兩個版本,一個廣色域和一個非廣版本,並使用 Python ImagesCms 庫進行轉換(這裡是一個方便的教程)。
#ICC_PROFILES是表示磁碟上的文件路徑的字元串converted_image n= ImageCms.profileToProfile(image, n DISPLAY_P3_ICC_PROFILE,n SRGB_ICC_PROFILE)n
在讀取時,我們的應用程序先判斷是否為廣色域圖像,並且後端以合適的配置文件動態地提供圖像。在將來,當大多數圖像都是廣色域,同時大多數顯示器都具備色彩管理時,我們可能會重新寫入演算法。
原文:Bringing Wide Color to Instagram
相關閱讀:
- Instagram的新衣:看Instagram首席設計師怎樣做設計
- UI 設計中顏色使用法則
- Python 的學習階段
歡迎關註:知乎專欄「極光日報」,每天為 Makers 導讀三篇優質英文文章。
推薦閱讀:
※SODO學堂 獨家教程 | 壓印戒指金工技法
※比有錢買房更牛逼的是,你有一個好的裝修品位…
※與其發一萬句我愛你,不如跟這些情話十級的大師取取經