Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Menyempurnakan grafis dengan konten warna lebar

Android 8.0 (API level 26) memperkenalkan dukungan pengelolaan warna untuk ruang warna tambahan selain RGB standar (sRGB) untuk merender grafis pada perangkat dengan tampilan yang kompatibel. Dengan dukungan ini, aplikasi Anda dapat merender bitmap dengan profil warna lebar tersemat yang dimuat dari file PNG, JPEG, dan WebP melalui Java atau kode native. Aplikasi yang menggunakan OpenGL atau Vulkan dapat langsung menampilkan konten wide color gamut (menggunakan Display P3 dan scRGB). Kemampuan ini berguna untuk membuat aplikasi yang melibatkan reproduksi warna high fidelty, seperti aplikasi pengeditan gambar dan video.

Memahami mode wide color gamut

Profil warna lebar merupakan profil ICC, seperti Adobe RGB, Pro Photo RGB, dan DCI-P3, yang mampu merepresentasikan rentang warna yang lebih luas daripada sRGB. Layar yang mendukung profil warna lebar dapat menampilkan gambar dengan warna primer yang lebih tajam (merah, hijau, dan biru) serta warna sekunder yang lebih kaya (seperti magenta, cyans, dan kuning).

Pada perangkat Android yang menjalankan Android 8.0 (API level 26) atau lebih tinggi yang mendukungnya, aplikasi Anda dapat mengaktifkan mode warna wide color gamut untuk aktivitas tempat sistem mengenali dan memproses gambar bitmap dengan benar menggunakan profil warna lebar yang tersemat. Class ColorSpace.Named mengenumerasi sebagian daftar ruang warna yang biasa digunakan dan didukung Android.

Catatan: Jika mode wide color gamut diaktifkan, jendela aktivitas akan menggunakan lebih banyak memori dan pemrosesan GPU untuk komposisi layar. Sebelum mengaktifkan mode wide color gamut, Anda harus mempertimbangkan dengan cermat apakah aktivitas tersebut benar-benar memperoleh keuntungan dari tindakan tersebut. Misalnya, aktivitas yang menampilkan foto dalam layar penuh adalah kandidat yang cocok untuk mode wide color gamut, tetapi aktivitas yang menampilkan thumbnail kecil tidak.

Mengaktifkan mode wide color gamut

Gunakan atribut colorMode untuk meminta aktivitas ditampilkan dalam mode wide color gamut pada perangkat yang kompatibel. Dalam mode wide color gamut, jendela dapat merender gamut di luar sRGB guna menampilkan warna yang lebih terang. Jika perangkat tidak mendukung rendering wide color gamut, atribut ini tidak berpengaruh apa pun. Jika aplikasi Anda perlu menentukan apakah layar yang ada mampu menampilkan wide color gamut, panggil metode isWideColorGamut(). Aplikasi Anda juga dapat memanggil isScreenWideColorGamut(), yang menampilkan true hanya jika layar mampu menampilkan wide color gamut dan perangkat mendukung rendering warna wide color gamut.

Layar mungkin mampu menampilkan wide color gamut tetapi tidak color-managed, dalam hal ini, sistem tidak akan mengizinkan mode wide color gamut ke aplikasi. Jika sebuah layar tidak color-managed, seperti yang terjadi pada semua versi Android sebelum 8.0—sistem akan memetakan ulang warna yang dihasilkan oleh aplikasi ke gamut tampilan.

Untuk mengaktifkan wide color gamut dalam aktivitas Anda, setel atribut colorMode ke wideColorGamut dalam file AndroidManifest.xml. Anda harus melakukan langkah ini untuk setiap aktivitas yang ingin Anda aktifkan mode warna lebarnya.

    android:colorMode="wideColorGamut"
    

Anda juga dapat menyetel mode warna secara terprogram dalam aktivitas dengan memanggil metode setColorMode(int) dan meneruskannya di COLOR_MODE_WIDE_COLOR_GAMUT.

Merender konten wide color gamut

Gambar 1. Ruang warna Display P3 (jingga) vs. sRGB (putih)

Untuk merender konten wide color gamut, aplikasi Anda harus memuat bitmap warna lebar, yaitu bitmap dengan profil warna yang berisi ruang warna yang lebih luas dari sRGB. Profil warna lebar biasanya mencakup Adobe RGB, DCI-P3 dan Display P3.

Aplikasi Anda dapat mengkueri ruang warna bitmap, dengan memanggil getColorSpace(). Untuk menentukan apakah sistem mengenali ruang warna tertentu sebagai gamut lebar, Anda dapat memanggil metode isWideGamut().

Class Color memungkinkan Anda menampilkan warna dengan empat komponen yang dikemas ke dalam nilai panjang 64 bit, bukan representasi paling umum yang menggunakan nilai bilangan bulat. Dengan nilai panjang, Anda dapat menentukan warna dengan lebih presisi daripada dengan nilai bilangan bulat. Jika perlu membuat atau mengenkode warna sebagai nilai panjang, gunakan salah satu metode pack() di class Color.

Anda dapat memverifikasi apakah aplikasi telah meminta mode wide color gamut dengan benar, dengan memeriksa apakah metode getColorMode() menampilkan COLOR_MODE_WIDE_COLOR_GAMUT (tetapi metode ini tidak menunjukkan apakah mode wide color gamut benar-benar diberikan atau tidak).

Menggunakan dukungan wide color gamut dalam kode native

Bagian ini menjelaskan cara mengaktifkan mode wide color gamut dengan API OpenGL dan Vulkan jika aplikasi Anda menggunakan kode native.

OpenGL

Untuk menggunakan mode wide color gamut di OpenGL, aplikasi Anda harus menyertakan library EGL 1.4 dengan salah satu ekstensi berikut:

Untuk mengaktifkan fitur ini, Anda harus membuat konteks GL terlebih dahulu melalui eglChooseConfig, dengan salah satu dari tiga format buffering warna yang didukung untuk warna lebar pada atribut. Format buffering warna untuk warna lebar harus merupakan salah satu dari rangkaian nilai RGBA ini:

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

Kemudian, minta ekstensi ruang warna P3 saat membuat target rendering, seperti yang ditunjukkan dalam cuplikan kode berikut:

    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

Dukungan Vulkan untuk wide color gamut disediakan melalui ekstensi VK_EXT_swapchain_colorspace.

Sebelum mengaktifkan dukungan warna lebar pada kode Vulkan Anda, periksa terlebih dahulu apakah ekstensinya didukung melalui vkEnumerateInstanceExtensionProperties. Jika ekstensi tersedia, Anda harus mengaktifkannya selama vkCreateInstance sebelum membuat gambar swapchain apa pun yang menggunakan ruang warna tambahan yang ditentukan oleh ekstensi.

Sebelum membuat swapchain, Anda harus memilih ruang warna yang Anda inginkan, lalu ulang melalui antarmuka perangkat fisik yang tersedia dan pilih format warna yang valid untuk ruang warna tersebut.

Pada perangkat Android, Vulkan mendukung wide color gamut dengan ruang warna dan format warna VkSurfaceFormatKHR berikut:

  • Ruang warna wide color gamut Vulkan:
    • VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
    • VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
  • Format warna Vulkan dengan dukungan wide color gamut:
    • VK_FORMAT_R16G16B16A16_SFLOAT
    • VK_FORMAT_A2R10G10B10_UNORM_PACK32
    • VK_FORMAT_R8G8B8A8_UNORM

Cuplikan kode berikut menunjukkan cara memeriksa apakah perangkat mendukung ruang warna 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
    }
    

Cuplikan kode berikut menunjukkan cara meminta swapchain Vulkan dengan 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;
    }