Xamarin.iOS 中的寬色
本文涵蓋寬色,以及如何在 Xamarin.iOS 或 Xamarin.Mac 應用程式中使用。
iOS 10 和 macOS Sierra 可增強整個系統的擴充範圍圖元格式和寬域色彩空間的支援,包括核心圖形、核心映像、金屬和 AVFoundation 等架構。 透過在整個圖形堆疊中提供此行為,可進一步簡化對全色顯示器裝置的支援。
資產目錄
使用資產目錄支援寬色
在 iOS 10 和 macOS Sierra 中,Apple 擴充了用來在應用程式套件組合中包含和分類靜態影像內容的資產類別目錄,以支援寬色。
使用資產目錄可為應用程式提供下列優點:
- 它們提供靜態映像資產的最佳部署選項。
- 它們支持自動色彩更正。
- 它們支援自動圖元格式優化。
- 它們支援應用程式配量和應用程式精簡,以確保只有相關的內容會傳遞至使用者的裝置。
Apple 已對資產類別目錄進行下列增強功能,以支援寬色:
- 它們支援16位(每個色彩通道)的來源內容。
- 它們支援透過顯示遊戲來編錄內容。 內容可以標記 sRGB 或 Display P3 遊戲。
開發人員有三個選項可支援其應用程式中的寬色內容:
- 不執行任何動作 - 因為寬色內容應該只在應用程式需要顯示生動色彩的情況下使用(他們將增強用戶體驗),因此,此需求以外的內容應保持現狀。 在所有硬體情況下,它將會繼續正確轉譯。
- 將現有內容升級為顯示 P3 - 這需要開發人員以 P3 格式的新升級檔案取代其資產目錄中的現有影像內容,並在資產編輯器中將它標記為這類檔案。 在建置階段,sRGB 衍生映射將會從這些資產產生。
- 提供優化資產內容 - 在此情況下,開發人員會提供資產類別目錄中每個影像的8位 sRGB 和16位的顯示 P3 視覺(在資產編輯器中正確標記)。
資產目錄部署
當開發人員使用包含寬色影像內容的資產類別目錄,將應用程式提交至 App Store 時,會發生下列情況:
- 將應用程式部署至使用者時,App Slicing 可確保只有適當的內容變體會傳遞至使用者的裝置。
- 在不支援寬色的裝置上,沒有包含寬色內容的承載成本,因為它永遠不會寄送到裝置。
NSImage
在macOS Sierra (及更新版本)上,會自動選取硬體顯示器的最佳內容表示法。- 當裝置硬體顯示特性變更時,系統會自動重新整理顯示的內容。
資產類別目錄 儲存體
資產類別目錄記憶體對應用程式具有下列屬性和含意:
- 在建置時,Apple 會嘗試透過高品質的影像轉換來優化影像內容的儲存。
- 每個色彩通道會使用16位,以取得寬色內容。
- 內容相依影像壓縮可用來降低交付內容大小。 已新增新的「遺失」壓縮,以進一步優化內容大小。
在應用程式中轉譯螢幕外影像
根據所建立的應用程式類型,它可能會允許使用者包含他們從因特網收集的影像內容,或直接在應用程式內部建立影像內容(例如向量繪圖應用程式)。
在這兩種情況下,應用程式可以使用新增至 iOS 和 macOS 的增強功能,以寬色呈現所需的影像。
在 iOS 中繪製寬色
在討論如何在 iOS 10 中正確繪製寬色影像之前,請先看看下列常見的 iOS 繪圖程式代碼:
public UIImage DrawWideColorImage ()
{
var size = new CGSize (250, 250);
UIGraphics.BeginImageContext (size);
...
UIGraphics.EndImageContext ();
return image = UIGraphics.GetImageFromCurrentImageContext ();
}
標準程式代碼有問題,必須先加以解決,才能用來繪製寬色影像。 UIGraphics.BeginImageContext (size)
用來啟動 iOS 影像繪製的方法有下列限制:
- 它無法建立每個色彩通道超過8位的影像內容。
- 它不能代表擴充範圍 sRGB 色彩空間中的色彩。
- 由於背景中呼叫低階 C 例程,所以無法提供介面,以在非 sRGB 色彩空間中建立內容。
若要處理這些限制,並在iOS 10 中繪製寬色影像,請改用下列程序代碼:
public UIImage DrawWideColorImage ()
{
var size = new CGSize (250, 250);
var render = new UIGraphicsImageRenderer (size);
var image = render.CreateImage ((UIGraphicsImageRendererContext context) => {
var bounds = context.Format.Bounds;
CGRect slice;
CGRect remainder;
bounds.Divide (bounds.Width / 2, CGRectEdge.MinXEdge, out slice, out remainder);
var redP3 = UIColor.FromDisplayP3 (1.0F, 0.0F, 0.0F, 1.0F);
redP3.SetColor ();
context.FillRect (slice);
var redRGB = UIColor.Red;
redRGB.SetColor ();
context.FillRect (remainder);
});
// Return results
return image;
}
新的 UIGraphicsImageRenderer
類別會建立新的影像內容,其能夠處理擴充範圍 sRGB 色彩空間,而且具有下列功能:
- 預設為完全色彩管理。
- 它默認支持擴充範圍 sRGB 色彩空間。
- 它會根據應用程式執行之 iOS 裝置的功能,以智慧方式決定它是否應該在 sRGB 或擴充範圍 sRGB 色彩空間中轉譯。
- 它完全且會自動管理映像內容 (
CGContext
) 存留期,因此開發人員不需要擔心呼叫開始和結束內容命令。 - 它與
UIGraphics.GetCurrentContext()
方法相容。
呼叫 類別 CreateImage
的 UIGraphicsImageRenderer
方法,以建立寬色影像,並使用影像內容傳遞完成處理程式來繪製。 所有繪圖都會在此完成處理程式內完成,如下所示:
- 方法
UIColor.FromDisplayP3
會在寬域顯示 P3 色彩空間中建立新的完全飽和紅色,並用來繪製矩形的前半部。 - 矩形的下半部會以標準 sRGB 完全飽和紅色繪製,以供比較。
在macOS中繪製寬色
類別 NSImage
已在macOS Sierra中展開,以支援「寬色」影像的繪製。 例如:
var size = CGSize(250,250);
var wideColorImage = new NSImage(size, false, (drawRect) =>{
var rects = drawRect.Divide(drawRect.Size.Width/2,CGRect.MinXEdge);
var color = new NSColor(1.0, 0.0, 0.0, 1.0).Set();
var path = new NSBezierPath(rects.Slice).Fill();
color = new NSColor(1.0, 0.0, 0.0, 1.0).Set();
path = new NSBezierPath(rects.Remainder).Fill();
// Return modified
return true;
});
在應用程式中轉譯螢幕影像
若要在螢幕上轉譯寬色影像,此程序的運作方式類似於為上面顯示的macOS和iOS繪製螢幕外寬色影像。
iOS 中的螢幕轉譯
當應用程式需要在 iOS 的螢幕上以寬色轉譯影像時,請如往常覆寫 Draw
有問題的方法 UIView
。 例如:
using System;
using UIKit;
using CoreGraphics;
namespace MonkeyTalk
{
public class MonkeyView : UIView
{
public MonkeyView ()
{
}
public override void Draw (CGRect rect)
{
base.Draw (rect);
// Draw the image to screen
...
}
}
}
如同 iOS 10 與 UIGraphicsImageRenderer
上述類別一樣,它會根據呼叫 方法時 Draw
執行之 iOS 裝置的功能,以智慧方式決定它是否應該在 sRGB 或 Extended Range sRGB 色彩空間中轉譯。 此外,自 UIImageView
iOS 9.3 之後,也已管理色彩。
如果應用程式必須知道如何在 或 UIViewController
上UIView
執行轉譯,它可以檢查 類別的新DisplayGamut
屬性UITraitCollection
。 此值將是 UIDisplayGamut
下列列舉:
- P3
- Srgb
- [未指定]
如果應用程式想要控制用來繪製影像的色彩空間,則可以使用 的新 ContentsFormat
屬性 CALayer
來指定所需的色彩空間。 此值可以是 CAContentsFormat
下列列舉:
- Gray8Uint
- Rgba16Float
- Rgba8Uint
在macOS中轉譯螢幕
當應用程式需要在 macOS 的螢幕上以寬色呈現影像時,請如往常覆寫 DrawRect
有問題的方法 NSView
。 例如:
using System;
using AppKit;
using CoreGraphics;
using CoreAnimation;
namespace MonkeyTalkMac
{
public class MonkeyView : NSView
{
public MonkeyView ()
{
}
public override void DrawRect (CGRect dirtyRect)
{
base.DrawRect (dirtyRect);
// Draw graphics into the view
...
}
}
}
同樣地,它會以智慧方式決定它是否應該根據呼叫 方法時 DrawRect
執行應用程式的Mac硬體功能,在 sRGB 或擴充範圍 sRGB 色彩空間中轉譯。
如果應用程式想要控制用來繪製影像的NSWindow
色彩空間,則可以使用 類別的新DepthLimit
屬性來指定所需的色彩空間。 此值可以是 NSWindowDepth
下列列舉:
- OneHundredTwentyEightBitRgb
- 60fourBitRgb
- TwentyfourBitRgb