Android 8.0 (API cấp 26) ra mắt tính năng hỗ trợ quản lý màu sắc cho không gian màu 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 sự hỗ trợ này, ứng dụng của bạn có thể kết xuất bitmap với cấu hình màu rộng được nhúng được tải từ tệp PNG, JPEG và WebP thông qua 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). Chức năng này hữu ích khi tạo các ứng dụng liên quan đến việc tái tạo màu có độ chân thực cao, chẳng hạn như hình ảnh và video chỉnh sửa ứng dụng.
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 gam màu rộng , bạn nên cân nhắc cẩn thận xem hoạt động đó có thực sự hưởng lợi từ nó 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ợ dải màu rộng
hiển thị gam màu, thuộc tính này không có hiệu ứng. 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 giá trị colorMode
cho 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 cách lập trình trong hoạt động của mình 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 cấu hình 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ột màu dưới dạng một 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 chế độ gam màu rộng đúng cách hay không bằng cách kiểm tra để đảm bảo
phương thức getColorMode()
trả về
COLOR_MODE_WIDE_COLOR_GAMUT
(phương pháp này không biểu thị,
tuy nhiên, 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 đó, yêu cầu tiện ích hệ màu P3 khi tạo đích hiển thị, như thể hiện 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 hệ màu mình muốn, sau đó lặp lại bề mặt thiết bị thực có sẵn và chọn định dạng màu hợp lệ cho bề mặt đó hệ màu.
Trên thiết bị Android, Vulkan hỗ trợ gam màu rộng với các hệ màu và
Định dạng màu VkSurfaceFormatKHR
:
- 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
- Các định dạng màu Vulkan 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 kiểm tra để đảm bảo rằng thiết bị có hỗ trợ Display P3 hệ màu:
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; }