W Androidzie 8.0 (poziom API 26) wprowadziliśmy obsługę zarządzania kolorami przestrzenie kolorów oprócz standardowy RGB (sRGB) do renderowania grafiki na urządzeniach ze zgodnymi wyświetlaczami. Dzięki temu wsparciu aplikacja może renderować mapy bitowe z osadzonymi szerokimi profilami kolorów wczytywanymi z plików PNG, JPEG i WebP za pomocą Javy lub kodu natywnego. Aplikacje korzystające z platformy OpenGL lub Vulkan mogą bezpośrednio generować treści o szerokiej gamie kolorów (za pomocą Display P3 oraz scRGB). Ta funkcja jest przydatne przy tworzeniu aplikacji wymagających wysokiej jakości reprodukcji kolorów, takich jak obrazy i filmy do edytowania aplikacji.
Omówienie trybu szerokiej gamy kolorów
Szerokie profile kolorów są profili ICC, takich jak Adobe RGB, Zdjęcie Pro RGB oraz DCI-P3, ale zdolny do reprezentowania szerszego zakresu kolorów niż sRGB. Ekrany obsługujące szerokie profile kolorów może wyświetlać obrazy o głębszych barwach podstawowych (czerwonych, zielonych i niebieskich) oraz bogatszych barwach drugorzędnych kolorów (takich jak purpurowe, błękitne i żółte).
Na urządzeniach z Androidem 8.0 (poziom interfejsu API 26) lub nowszym, które go obsługują, aplikacja może:
włączyć tryb kolorów szerokiej gamy kolorów dla aktywności, w której system rozpoznaje i
poprawnie przetwarza obrazy bitmapy z osadzonymi szerokimi profilami kolorów.
Klasa ColorSpace.Named
wylicza częściową listę często używanych
przestrzeni kolorów obsługiwanych przez Androida.
Uwaga: gdy włączony jest tryb szerokiej gamy kolorów, używa więcej pamięci i procesora GPU do tworzenia kompozycji ekranu. Zanim włączysz szerszą gamę kolorów należy dokładnie zastanowić się, czy dana aktywność przynosi korzyści. Na przykład funkcja wyświetlania zdjęć na pełnym ekranie jest dobrym rozwiązaniem do stosowania w trybie szerokiej gamy kolorów, aktywność, która pokazuje małe miniatury, już nie.
Włącz tryb szerokiej gamy kolorów
Użyj atrybutu colorMode
, aby poprosić o wyświetlenie aktywności
w trybie szerokiej gamy kolorów na zgodnych urządzeniach. W trybie szerokiej gamy kolorów okno może renderować się
poza zakresem sRGB, aby wyświetlić bardziej żywe kolory. Jeśli urządzenie nie obsługuje szerokich kolorów
gamut, ten atrybut nie ma żadnego efektu. Jeśli aplikacja musi określić, czy
obsługuje szeroki zakres kolorów, wywołaj funkcję
Metoda isWideColorGamut()
. Możesz też zadzwonić do
isScreenWideColorGamut()
, która zwraca true
tylko wtedy, gdy wyświetlacz obsługuje szeroki zakres kolorów, a urządzenie obsługuje szerszą gamę kolorów.
renderowanie kolorów.
Ekran może obsługiwać szeroką gamę kolorów, ale nie może zarządzać kolorami. W takim przypadku funkcja system nie przyzna aplikacji trybu szerokiej gamy kolorów. Gdy wyświetlacz nie jest zarządzany kolorem – tak jak we wszystkich wersjach Androida sprzed 8.0 – system ponownie mapuje kolorów wybranych przez aplikację do palety wyświetlacza.
Aby włączyć w swojej aktywności szeroką gamę kolorów, ustaw colorMode
wideColorGamut
w pliku AndroidManifest.xml
. Ty
Zrobisz to w przypadku każdej aktywności, dla której chcesz włączyć tryb szerokiego kolorów.
android:colorMode="wideColorGamut"
Tryb kolorów możesz też automatycznie ustawić w aktywności, używając
Metoda setColorMode(int)
i przekazywanie
COLOR_MODE_WIDE_COLOR_GAMUT
Renderuj zawartość o szerokim zakresie kolorów
Aby renderować treści o szerokiej gamie kolorów, aplikacja musi wczytać dużą mapę bitową kolorów, czyli profil kolorów zawierający przestrzeń kolorów szerszą niż sRGB. Typowe szerokie profile kolorów to Adobe RGB, DCI-P3 i Display P3.
Aplikacja może wysyłać zapytania o przestrzeń kolorów bitmapy, wywołując
getColorSpace()
Aby określić, czy system rozpoznaje
konkretnej przestrzeni kolorów, możesz nazywać
Metoda isWideGamut()
.
Klasa Color
umożliwia określenie koloru za pomocą 4 komponentów.
zapisany do 64-bitowej wartości, zamiast reprezentacji najczęściej używanej liczby całkowitej
. Używając długich wartości, możesz definiować kolory za pomocą
większą precyzję niż wartości całkowite. Jeśli chcesz utworzyć lub zakodować kolor jako długą wartość, użyj funkcji
jedną z metod pack()
w klasie Color
.
Aby się dowiedzieć, czy aplikacja poprawnie zażądała trybu szerokiej gamy kolorów, sprawdź
metoda getColorMode()
zwraca
COLOR_MODE_WIDE_COLOR_GAMUT
(ta metoda nie wskazuje,
czy tryb szerokiej gamy kolorów został rzeczywiście przyznany).
Używanie obsługi szerokiej gamy kolorów w kodzie natywnym
W tej sekcji opisujemy, jak włączyć tryb szerokiej gamy kolorów za pomocą funkcji OpenGL i interfejsów API Vulkan, jeśli aplikacja używa kodu natywnego.
OpenGL
Aby można było używać trybu szerokiej gamy kolorów w trybie OpenGL, aplikacja musi zawierać bibliotekę EGL 1.4 z jedno z tych rozszerzeń:
Aby włączyć tę funkcję, musisz najpierw utworzyć kontekst GL za pomocą
eglChooseConfig
, gdzie jedna z 3 obsługiwanych:
formatów bufora kolorów,
aby uzyskać szeroki kolor. Format bufora kolorów dla szerokiego
kolor musi być jednym z następujących zbiorów wartości RGBA:
- 8, 8, 8, 8
- 10, 10, 10, 2
- FP16, FP16, FP16, FP16
Następnie podczas tworzenia przestrzeni kolorów P3 poproś o rozszerzenie przestrzeni kolorów zgodnie z tym fragmentem kodu:
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());
Wulkan
Obsługę interfejsu Vulkan w przypadku szerokiej gamy kolorów zapewnia
VK_EXT_swapchain_colorspace
.
Zanim włączysz obsługę szerokich kolorów w kodzie Vulkan, najpierw sprawdź, czy
rozszerzenie jest obsługiwane przez
vkEnumerateInstanceExtensionProperties
Jeśli rozszerzenie jest dostępne, musisz je włączyć w czasie, gdy
vkCreateInstance
.
należy użyć dodatkowych przestrzeni kolorów zdefiniowanych przez rozszerzenie.
Przed utworzeniem łańcucha kolorów musisz wybrać odpowiednią przestrzeń kolorów, a potem wykonać pętlę na dostępnych powierzchniach na urządzeniach fizycznych i wybrać odpowiedni format kolorów. przestrzeni kolorów.
Na urządzeniach z Androidem Vulkan obsługuje szeroką gamę kolorów z następującymi przestrzeniami kolorów i
Formaty kolorów (VkSurfaceFormatKHR
):
- Przestrzenie kolorów w szerokej gamie kolorów Vulkan:
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
- Formaty kolorów Vulkan z obsługą szerokiej gamy kolorów:
VK_FORMAT_R16G16B16A16_SFLOAT
VK_FORMAT_A2R10G10B10_UNORM_PACK32
VK_FORMAT_R8G8B8A8_UNORM
Ten fragment kodu pokazuje, jak sprawdzić, czy urządzenie obsługuje format Display P3. przestrzeń kolorów:
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 }
Fragment kodu poniżej pokazuje, jak poprosić o zamianę interfejsu Vulkan na
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; }