Android 8.0 (API cấp 26) đã ra mắt tính năng hỗ trợ quản lý màu sắc cho các không gian màu bổ sung bên cạnh RGB (sRGB) tiêu chuẩn để kết xuất đồ hoạ trên các thiết bị có màn hình tương thích. Với tính năng hỗ trợ này, ứng dụng của bạn có thể kết xuất bitmap có cấu hình màu rộng được nhúng được tải từ các tệp PNG, JPEG và WebP thông qua mã Java hoặc mã gốc. Các ứng dụng sử dụng OpenGL hoặc Vulkan có thể trực tiếp tạo ra nội dung gam màu rộng (sử dụng Display P3 và scRGB). Khả năng này rất hữu ích khi tạo các ứng dụng có liên quan đến việc tái tạo màu sắc có độ chân thực cao, chẳng hạn như các ứng dụng chỉnh sửa hình ảnh và video.
Tìm hiểu về chế độ gam màu rộng
Hồ sơ màu rộng Hồ sơ ICC, chẳng hạn như Adobe RGB, Pro Photo RGB và DCI-P3, tức là có khả năng thể hiện dải màu rộng hơn so với sRGB. Màn hình hỗ trợ cấu hình màu rộng có thể hiển thị hình ảnh có các màu cơ bản sâu sắc hơn (đỏ, xanh lục và xanh lam) cũng như các hình ảnh phụ phong phú hơn (chẳng hạn như đỏ tươi, xanh lơ và vàng).
Trên thiết bị Android chạy Android 8.0 (API cấp 26) trở lên có hỗ trợ phiên bản này, ứng dụng của bạn có thể
bật chế độ màu gam màu rộng cho một hoạt động, trong đó hệ thống nhận dạng và
xử lý chính xác hình ảnh bitmap với cấu hình màu rộng được nhúng. Chiến lược phát hành đĩa đơn
Lớp ColorSpace.Named
liệt kê một phần danh sách các lớp thường dùng
hệ màu mà Android hỗ trợ.
Lưu ý: Khi bạn bật chế độ gam màu rộng, giá trị cửa sổ sử dụng nhiều bộ nhớ và xử lý GPU hơn cho cấu trúc màn hình. Trước khi bật chế độ gam màu rộng, bạn nên cân nhắc kỹ xem hoạt động có thực sự hưởng lợi từ chế độ này hay không. Ví dụ: một hiển thị hình ảnh ở chế độ toàn màn hình là một lựa chọn phù hợp cho chế độ gam màu rộng, nhưng thì hoạt động có hiển thị hình thu nhỏ nhỏ thì không.
Bật chế độ gam màu rộng
Dùng thuộc tính colorMode
để yêu cầu hiển thị hoạt động
ở chế độ gam màu rộng trên các thiết bị tương thích. Ở chế độ gam màu rộng, một cửa sổ có thể hiển thị bên ngoài gam màu sRGB để hiển thị các màu rực rỡ hơn. Nếu thiết bị không hỗ trợ tính năng hiển thị gam màu rộng, thì thuộc tính này sẽ không có hiệu lực. Nếu ứng dụng của bạn cần xác định xem một
màn hình có gam màu rộng, hãy gọi phương thức
isWideColorGamut()
. Ứng dụng của bạn cũng có thể gọi
isScreenWideColorGamut()
, trả về true
chỉ khi màn hình có gam màu rộng và thiết bị hỗ trợ gam màu rộng
kết xuất màu.
Một màn hình có thể có gam màu rộng nhưng không được quản lý màu. Trong trường hợp đó, hệ thống sẽ không cấp cho ứng dụng chế độ gam màu rộng. Khi màn hình không được quản lý bằng màu sắc —như trường hợp của tất cả các phiên bản Android trước 8.0 — hệ thống đã ánh xạ lại các màu do ứng dụng vẽ theo gam màu của màn hình.
Để bật gam màu rộng trong hoạt động, hãy đặt thuộc tính colorMode
thành wideColorGamut
trong tệp AndroidManifest.xml
. Bạn
cần thực hiện việc này cho từng hoạt động mà bạn muốn bật chế độ màu rộng.
android:colorMode="wideColorGamut"
Bạn cũng có thể đặt chế độ màu theo phương thức lập trình trong hoạt động bằng cách gọi phương thức setColorMode(int)
và truyền vào COLOR_MODE_WIDE_COLOR_GAMUT
.
Hiển thị nội dung gam màu rộng
Để hiển thị nội dung gam màu rộng, ứng dụng của bạn phải tải một bitmap màu rộng, đó là một bitmap có cấu hình màu chứa hệ màu rộng hơn sRGB. Các hồ sơ màu rộng phổ biến bao gồm Adobe RGB, DCI-P3 và Display P3.
Ứng dụng có thể truy vấn hệ màu của bitmap bằng cách gọi
getColorSpace()
. Để xác định xem hệ thống có nhận ra một
hệ màu cụ thể là gam rộng, bạn có thể gọi hàm
isWideGamut()
.
Lớp Color
cho phép bạn biểu thị màu bằng 4 thành phần
được đóng gói thành một giá trị dài 64 bit, thay vì cách biểu diễn phổ biến nhất sử dụng số nguyên
giá trị. Khi sử dụng các giá trị dài, bạn có thể xác định màu bằng
chính xác hơn giá trị số nguyên. Nếu bạn cần tạo hoặc mã hoá màu dưới dạng giá trị dài, hãy sử dụng một trong các phương thức pack()
trong lớp Color
.
Bạn có thể xác minh xem ứng dụng của mình có yêu cầu đúng cách chế độ gam màu rộng hay không bằng cách kiểm tra xem phương thức getColorMode()
có trả về COLOR_MODE_WIDE_COLOR_GAMUT
hay không (tuy nhiên, phương thức này không cho biết liệu chế độ gam màu rộng có thực sự được cấp hay không).
Sử dụng tính năng hỗ trợ gam màu rộng trong mã gốc
Phần này mô tả cách bật chế độ gam màu rộng bằng OpenGL và Các API Vulkan nếu ứng dụng của bạn dùng mã gốc.
OpenGL
Để sử dụng chế độ gam màu rộng trong OpenGL, ứng dụng của bạn phải chứa thư viện EGL 1.4 có một trong các tiện ích sau:
Để bật tính năng này, trước tiên, bạn phải tạo bối cảnh GL qua
eglChooseConfig
, với 1 trong 3 tính năng được hỗ trợ
định dạng vùng đệm màu cho màu rộng trong các thuộc tính. Định dạng vùng đệm màu cho quảng cáo rộng
màu phải là một trong các nhóm giá trị RGBA sau:
- 8, 8, 8, 8
- 10, 10, 10, 2
- FP16, FP16, FP16, FP16
Sau đó, hãy yêu cầu tiện ích không gian màu P3 khi tạo mục tiêu kết xuất, như minh hoạ trong đoạn mã sau:
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
Tính năng hỗ trợ Vulkan cho gam màu rộng được cung cấp thông qua
VK_EXT_swapchain_colorspace
.
Trước khi bật tính năng hỗ trợ màu rộng trong mã Vulkan, trước tiên, hãy kiểm tra xem
tiện ích được hỗ trợ qua
vkEnumerateInstanceExtensionProperties
.
Nếu tiện ích này có sẵn, bạn phải bật tiện ích đó trong thời gian
vkCreateInstance
trước khi tạo bất kỳ hình ảnh chuỗi hoán đổi nào
sử dụng hệ màu bổ sung do tiện ích xác định.
Trước khi tạo chuỗi hoán đổi, bạn cần chọn không gian màu mong muốn, sau đó lặp lại các bề mặt thiết bị thực có sẵn và chọn một định dạng màu hợp lệ cho không gian màu đó.
Trên thiết bị Android, Vulkan hỗ trợ gam màu rộng với các không gian màu và định dạng màu VkSurfaceFormatKHR
sau đây:
- Hệ màu gam màu rộng của Vulkan:
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
- Định dạng màu Vulkan có hỗ trợ gam màu rộng:
VK_FORMAT_R16G16B16A16_SFLOAT
VK_FORMAT_A2R10G10B10_UNORM_PACK32
VK_FORMAT_R8G8B8A8_UNORM
Đoạn mã sau đây cho biết cách bạn có thể kiểm tra xem thiết bị có hỗ trợ không gian màu Hiển thị P3 hay không:
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 }
Đoạn mã sau đây cho biết cách yêu cầu một chuỗi hoán đổi Vulkan bằng 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; }