広色域コンテンツでグラフィックを強化する

Android 8.0(API レベル 26)では、追加のカラー マネージメント サポートが導入されました。 色スペース 対応ディスプレイを備えたデバイスでのグラフィックのレンダリングに使用する標準 RGB(sRGB)です。このサポートにより PNG、JPEG、WebP ファイルから読み込まれた埋め込みのワイドカラー プロファイルを使用してビットマップをレンダリングできる ネイティブコードで実装できますOpenGL または Vulkan を使用するアプリは、広色域コンテンツを直接出力できる (Display P3scRGB など)にマッピングされます。この機能は 画像や動画など、色を再現するアプリの作成に便利 アプリを編集しています。

広色域モードを理解する

広色域プロファイルは ICC プロファイル: Adobe RGB、 <ph type="x-smartling-placeholder"></ph> プロフォト RGB DCI-P3: sRGB よりも幅広い色を表現できます。広色域プロファイルをサポートする画面 より濃いプライマリ カラー(赤、緑、青)と豊かなセカンダリ カラーで画像を表示できます (マゼンタ、シアン、イエローなど)。

Android 8.0(API レベル 26)以降を搭載し、それをサポートしている Android デバイスでは、 アクティビティに対して広色域モードを有効にして、システムが 埋め込みワイドカラー プロファイルを使用してビットマップ画像を正しく処理します。「 ColorSpace.Named クラスは、よく使用されるアプリケーションの部分リストを列挙 Android がサポートする色空間です。

注: 広色域モードが有効になっている場合、アクティビティの 画面の合成に使用するメモリと GPU 処理が増えます。広色域を有効にする前に アクティビティが本当にその恩恵を受けているかどうかを慎重に検討する必要があります。たとえば、 写真を全画面で表示するアクティビティは、広色域モードに適していますが、 小さいサムネイルを表示するアクティビティは認識されません。

広色域モードを有効にする

colorMode 属性を使用して、アクティビティの表示をリクエストする 対応デバイスで広色域モードで表示できます広色域モードではウィンドウを 色を鮮やかに表示するために使用できますデバイスが広色域に対応していない場合 色域レンダリングを使用した場合、この属性は機能しません。特定のしきい値を許容するかどうかを ディスプレイが広色域に対応している場合、 isWideColorGamut() メソッドを使用します。また、 isScreenWideColorGamut()true を返します) ディスプレイが広色域に対応しており、デバイスが広色域をサポートしている場合のみ 開発できます

ディスプレイは、広色域に対応していても色管理ができないことがあります。その場合は、 広色域モードがアプリに許可されません。ディスプレイがカラー マネージメントでない場合 8.0 より前のすべてのバージョンの Android がそうであったように、 アプリによってディスプレイの色域に描画された色。

アクティビティで広色域を有効にするには、colorMode を設定します。 AndroidManifest.xml ファイル内で wideColorGamut にこの属性を追加します。マイページ この操作は、広色域モードを有効にするアクティビティごとに行う必要があります。

android:colorMode="wideColorGamut"

また、次のように呼び出して、アクティビティで色モードをプログラムで設定することもできます。 setColorMode(int) メソッドを使用し、 COLOR_MODE_WIDE_COLOR_GAMUT

広色域コンテンツをレンダリングする

<ph type="x-smartling-placeholder">
</ph>
図 1.ディスプレイの P3(オレンジ)と sRGB(白)の色空間

広色域コンテンツをレンダリングするには、広色域ビットマップ( sRGB よりも広い色空間を含むカラー プロファイル。一般的な広色域プロファイルには、 Adobe RGB、DCI-P3、Display P3。

ビットマップの色空間をクエリするには、 getColorSpace()。システムが 広色域でレンダリングしたい場合は isWideGamut() メソッドを使用します。

Color クラスを使用すると、4 つのコンポーネントで色を表現できます。 64 ビット長の値にパックされます。これは、整数を使用する最も一般的な表現ではありません。 あります。長い値を使用すると、 精度が高くなります色を long 値として作成またはエンコードする必要がある場合は、次のコマンドを使用します。 Color クラスの pack() メソッドのいずれか。

アプリが広色域モードを適切にリクエストしているかどうかは、 getColorMode() メソッドが返す COLOR_MODE_WIDE_COLOR_GAMUT(このメソッドは、 (広色域モードが実際に許可されたかどうか)などです。

ネイティブ コードで広色域サポートを使用する

このセクションでは、 OpenGL と アプリがネイティブ コードを使用する場合、Vulkan API。

OpenGL

OpenGL で広色域モードを使用するには、EGL 1.4 ライブラリを 次のいずれかの拡張機能を使用できます。

この機能を有効にするには、まず eglChooseConfig(サポートされている 3 つのうちのいずれか) 広色域用のカラーバッファ形式を属性内で使用しています。ワイド広告のカラーバッファ形式 color は次のいずれかの RGBA 値にする必要があります。

  • 8, 8, 8, 8
  • 10, 10, 10, 2
  • FP16、FP16、FP16、FP16

P3 色空間拡張をリクエストする際には、 レンダリング ターゲットを、次のコード スニペットに示します。

std::vector<EGLint> attributes;
attributes.push_back(EGL_GL_COLORSPACE_KHR);
attributes.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
attributes.push_back(EGL_NONE);
engine->surface_ = eglCreateWindowSurface(
    engine->display_, config, engine->app->window, attributes.data());

Vulkan

広色域の Vulkan サポートは、 VK_EXT_swapchain_colorspace 拡張機能。

Vulkan コードで広色域サポートを有効にする前に、 以下を介してサポートされます。 vkEnumerateInstanceExtensionProperties。 拡張機能が利用可能な場合は、 vkCreateInstance の後に、スワップチェーン イメージを作成します。 拡張機能で定義された追加の色空間を使用します。

スワップチェーンを作成する前に、必要な色空間を選択し、 有効なカラー形式を選択している 色空間を指定します。

Android デバイスの Vulkan は、次の色空間を持つ広色域をサポートしています。 VkSurfaceFormatKHR カラー形式:

  • Vulkan の広色域色空間: <ph type="x-smartling-placeholder">
      </ph>
    • VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
    • VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
  • 広色域をサポートする Vulkan 色形式: <ph type="x-smartling-placeholder">
      </ph>
    • VK_FORMAT_R16G16B16A16_SFLOAT
    • VK_FORMAT_A2R10G10B10_UNORM_PACK32
    • VK_FORMAT_R8G8B8A8_UNORM

次のコード スニペットは、デバイスが Display P3 に対応していることを確認する方法を示しています。 色空間:

uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(
       vkPhysicalDev,
       vkSurface,
       &formatCount,
       nullptr);
VkSurfaceFormatKHR *formats = new VkSurfaceFormatKHR[formatCount];
vkGetPhysicalDeviceSurfaceFormatsKHR(
       vkPhysicalDev,
       vkSurface,
       &formatCount,
       formats);

uint32_t displayP3Index = formatCount;
for (uint32_t idx = 0; idx < formatCount; idx++) {
 if (formats[idx].format == requiredSwapChainFmt &&
     formats[idx].colorSpace==VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT)
 {
   displayP3Index = idx;
   break;
 }
}
if (displayP3Index == formatCount) {
    // Display P3 is not supported on the platform
    // choose other format
}

次のコード スニペットは、以下を含む Vulkan スワップチェーンをリクエストする方法を示しています。 VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:

uint32_t queueFamily = 0;
VkSwapchainCreateInfoKHR swapchainCreate {
   .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
   .pNext = nullptr,
   .surface = AndroidVkSurface_,
   .minImageCount = surfaceCapabilities.minImageCount,
   .imageFormat = requiredSwapChainFmt,
   .imageColorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
   .imageExtent = surfaceCapabilities.currentExtent,
   .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
   .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
   .imageArrayLayers = 1,
   .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
   .queueFamilyIndexCount = 1,
   .pQueueFamilyIndices = &queueFamily,
   .presentMode = VK_PRESENT_MODE_FIFO_KHR,
   .oldSwapchain = VK_NULL_HANDLE,
   .clipped = VK_FALSE,
};
VkRresult status = vkCreateSwapchainKHR(
                       vkDevice,
                       &swapchainCreate,
                       nullptr,
                       &vkSwapchain);
if (status != VK_SUCCESS) {
    // Display P3 is not supported
    return false;
}