Migliora la grafica con contenuti a colori ampi

Android 8.0 (livello API 26) ha introdotto il supporto della gestione del colore per spazi colore oltre a RGB (sRGB) standard per il rendering di grafica su dispositivi con display compatibili. Grazie a questo supporto, la tua app può eseguire il rendering delle bitmap con profili di colore larghi incorporati caricati da file PNG, JPEG e WebP tramite Java o codice nativo. Le app che utilizzano OpenGL o Vulkan possono produrre direttamente contenuti con ampia gamma di colori (utilizzando Display P3 e scRGB). Questa funzionalità è utile per creare app che prevedono una riproduzione dei colori ad alta fedeltà, come immagini e video app di editing.

Informazioni sulla modalità ad ampia gamma di colori

I profili di colore larghi vengono Profili ICC, ad esempio Adobe RGB, Foto professionale RGB e DCI-P3, ovvero in grado di rappresentare una gamma più ampia di colori rispetto a sRGB. Schermi che supportano ampi profili di colore possono visualizzare immagini con colori primari più scuri (rossi, verdi e blu) nonché colori secondari più intensi colori (come magenta, ciano e giallo).

Sui dispositivi Android con Android 8.0 (livello API 26) o versioni successive che lo supportano, la tua app può attivare la modalità di colore gamma di colori ampia per un'attività in cui il sistema riconosce e elaborare correttamente le immagini bitmap con profili di colore larghi incorporati. La La classe ColorSpace.Named elenca un elenco parziale dei spazi colore supportati da Android.

Nota: quando è attiva la modalità gamma di colori ampia, i parametri dell'attività usa più memoria e più elaborazione GPU per la composizione dello schermo. Prima di attivare un'ampia gamma di colori devi valutare attentamente se l'attività ne beneficia davvero. Ad esempio, un l'attività che mostra foto a schermo intero è una buona candidata per la modalità ad ampia gamma di colori, ma un'attività che mostra miniature piccole lo è.

Attiva modalità gamma di colori ampia

Utilizza l'attributo colorMode per richiedere che l'attività venga visualizzata in modalità ad ampia gamma di colori sui dispositivi compatibili. In modalità gamma di colori ampia, è possibile eseguire il rendering di una finestra al di fuori della gamma sRGB per mostrare colori più vivaci. Se il dispositivo non supporta i colori larghi gamut, questo attributo non ha alcun effetto. Se la tua app deve determinare se un determinato il display supporta un'ampia gamma di colori, chiama isWideColorGamut(). L'app può anche chiamare isScreenWideColorGamut(), che restituisce true solo se il display supporta un'ampia gamma di colori e il dispositivo supporta un'ampia gamma di colori resa cromatica.

Un display potrebbe supportare un'ampia gamma di colori ma non una gestione del colore. In questo caso, non concederà a un'app la modalità ad ampia gamma di colori. Quando un display non è gestito per colore , come per tutte le versioni di Android precedenti alla 8.0, il sistema rimappa colori disegnati dall'app alla gamma del display.

Per attivare l'ampia gamma di colori nella tua attività, imposta colorMode a wideColorGamut nel file AndroidManifest.xml. Tu devi farlo per ogni attività per cui vuoi abilitare la modalità colore largo.

android:colorMode="wideColorGamut"

Puoi anche impostare in modo programmatico la modalità colore nella tua attività richiamando il metodo setColorMode(int) e passaggio COLOR_MODE_WIDE_COLOR_GAMUT.

Visualizzazione di contenuti con ampia gamma di colori

Figura 1. Display con spazi colore P3 (arancione) e sRGB (bianco)

Per eseguire il rendering di contenuti con gamma di colori ampia, l'app deve caricare una bitmap a colori ampi, ovvero una bitmap con un profilo di colore contenente uno spazio colore più ampio di sRGB. I profili di colore larghi più comuni includono Adobe RGB, DCI-P3 e Display P3.

La tua app può eseguire query sullo spazio colore di una bitmap chiamando getColorSpace(). Per determinare se il sistema riconosce un spazio colore specifico per avere un'ampia gamma, puoi richiamare isWideGamut().

La classe Color ti consente di rappresentare un colore con quattro componenti pacchettizzati in un valore lungo a 64 bit, invece della rappresentazione più comune che utilizza un numero intero valore. Utilizzando valori lunghi, puoi definire i colori con e maggiore precisione rispetto ai valori interi. Se devi creare o codificare un colore come valore lungo, utilizza uno dei metodi pack() della classe Color.

Per verificare se la tua app ha richiesto correttamente la modalità ad ampia gamma di colori, controlla che Il metodo getColorMode() restituisce COLOR_MODE_WIDE_COLOR_GAMUT (questo metodo non indica, tuttavia, se la modalità ad ampia gamma di colori è stata effettivamente concessa.

Utilizzare il supporto di un'ampia gamma di colori nel codice nativo

In questa sezione viene descritto come attivare la modalità ad ampia gamma di colori con il OpenGL e API Vulkan se la tua app utilizza codice nativo.

OpenGL

Per utilizzare la modalità ad ampia gamma di colori in OpenGL, l'app deve includere la libreria EGL 1.4 con una delle seguenti estensioni:

Per attivare la funzionalità, devi prima creare un contesto GL tramite eglChooseConfig, con uno dei tre supportati formati di buffer di colore per colori ampi negli attributi. Il formato del buffer di colore per le immagini il colore deve essere uno dei seguenti insiemi di valori RGBA:

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

Quindi, richiedi l'estensione dello spazio colore P3 durante la creazione target di rendering, come illustrato nello snippet di codice riportato di seguito:

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

Il supporto di Vulkan per un'ampia gamma di colori viene fornito tramite la VK_EXT_swapchain_colorspace.

Prima di abilitare il supporto dei colori ampi nel codice Vulkan, verifica innanzitutto che il valore è supportata tramite vkEnumerateInstanceExtensionProperties. Se l'estensione è disponibile, devi abilitarla durante vkCreateInstance prima di creare immagini swapchain utilizza gli spazi colore aggiuntivi definiti dall'estensione.

Prima di creare la swapchain, è necessario scegliere lo spazio colore desiderato, quindi scorrere la piattaforme dispositivi fisici disponibili e scegli un formato di colore valido spazio colore.

Sui dispositivi Android, Vulkan supporta un'ampia gamma di colori con i seguenti spazi colore e VkSurfaceFormatKHR formati di colore:

  • Spazi cromatici con gamma di colori Vulkan ampia:
      .
    • VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
    • VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
  • Formati di colore Vulkan con supporto di un'ampia gamma di colori:
      .
    • VK_FORMAT_R16G16B16A16_SFLOAT
    • VK_FORMAT_A2R10G10B10_UNORM_PACK32
    • VK_FORMAT_R8G8B8A8_UNORM

Il seguente snippet di codice mostra come verificare che il dispositivo supporti il Display P3 spazio colore:

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
}

Il seguente snippet di codice mostra come richiedere uno swapchain Vulkan con 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;
}