ב-Android 8.0 (רמת API 26) נוספה תמיכה בניהול צבעים במרחבי צבעים נוספים, בנוסף ל-RGB (sRGB) הסטנדרטי, לצורך עיבוד גרפיקה במכשירים עם מסכים תואמים. בעזרת התמיכה הזו, האפליקציה יכולה ליצור עיבוד (רנדור) של בימפטים עם פרופילי צבע רחבים מוטמעים, שנטענים מקובצי PNG, JPEG ו-WebP באמצעות Java או קוד מקורי. אפליקציות שמשתמשות ב-OpenGL או ב-Vulkan יכולות להפיק תוכן עם מגוון רחב של צבעים ישירות (באמצעות Display P3 ו-scRGB). היכולת הזו שימושי ליצירת אפליקציות שכוללות שחזור של צבעים באיכות גבוהה, כמו תמונות וסרטונים עריכת אפליקציות.
הסבר על מצב של טווח צבעים רחב
פרופילים של צבעים רחבים הם פרופילים של ICC, כמו Adobe RGB, Pro Photos RGB, וגם DCI-P3, שיכול לייצג מגוון רחב יותר של צבעים מאשר sRGB. מסכים שתומכים בפרופילים של צבעים רחבים ניתן להציג תמונות בעלות צבעי יסוד עמוקים יותר (אדום, ירוק וכחול) וכן תמונות משניות עשירות יותר צבעים (כגון מג'נטה, ציאן וצהוב).
במכשירי Android עם Android 8.0 ואילך (רמת API 26 ואילך) שתומכים בכך, האפליקציה יכולה להפעיל את מצב הצבע של מגוון רחב של צבעים לפעילות מסוימת, שבה המערכת מזהה תמונות בפורמט בייטמאפ עם פרופילים מוטמעים של מגוון רחב של צבעים ומעבדת אותן בצורה נכונה.
כיתה ColorSpace.Named
מסווגת רשימה חלקית של כלים נפוצים
מרחבי צבעים שנתמכים ב-Android.
הערה: כשמצב 'סולם צבעים רחב' מופעל, החלון משתמש ביותר זיכרון ובעיבוד GPU להרכבת המסך. לפני שמפעילים את המצב של מגוון רחב של צבעים, כדאי לבדוק היטב אם הוא באמת משפר את הפעילות. לדוגמה, פעילות שמציגה תמונות במסך מלא מתאימה למצב של סולם צבעים רחב, פעילות שמציגה תמונות ממוזערות קטנות היא לא פעילות.
הפעלת מצב של מגוון רחב של צבעים
אפשר להשתמש במאפיין colorMode
כדי לבקש שהפעילות תוצג במצב של מגוון רחב של צבעים במכשירים תואמים. במצב של מרחב צבעים רחב, חלון יכול לבצע רינדור מחוץ למרחב הצבעים sRGB כדי להציג צבעים מלאי חיים יותר. אם המכשיר לא תומך בצבע רחב
עיבוד סולם, למאפיין הזה אין השפעה. אם האפליקציה שלך צריכה להחליט אם
לתצוגה יש סולם צבעים רחב,
אמצעי תשלום אחד (isWideColorGamut()
). האפליקציה יכולה גם להתקשר
isScreenWideColorGamut()
, שמחזיר true
רק אם המסך תומך בסולם צבעים רחב והמכשיר תומך במערך צבעים רחב.
ורינדור.
יכול להיות שמסך מסוים תומך בטווח רחב של צבעים אבל לא כולל ניהול צבעים. במקרה כזה, המערכת לא תעניק לאפליקציה את מצב טווח רחב של צבעים. כשהתצוגה לא מנוהלת לפי צבעים —כפי שהיה בכל הגרסאות של Android לפני 8.0 — המערכת תמפה מחדש את צבעים שהאפליקציה יצרה לסולם התצוגה.
כדי להפעיל את מגוון הצבעים הרחב בפעילות, מגדירים את המאפיין colorMode
לערך wideColorGamut
בקובץ AndroidManifest.xml
. צריך לעשות זאת לכל פעילות שרוצים להפעיל בה את מצב צבע רחב.
android:colorMode="wideColorGamut"
אפשר גם להגדיר את מצב הצבע באופן פרוגרמטי בפעילות על ידי קריאה לשיטה setColorMode(int)
והעברת הערך COLOR_MODE_WIDE_COLOR_GAMUT
.
עיבוד תוכן של סולם צבעים רחב
כדי להציג תוכן עם מגוון רחב של צבעים, האפליקציה צריכה לטעון קובץ בייטמאפ עם מגוון רחב של צבעים, כלומר קובץ בייטמאפ עם פרופיל צבע שמכיל מרחב צבעים רחב יותר מ-sRGB. פרופילים נפוצים של מרחב צבעים רחב כוללים את Adobe RGB, DCI-P3 ו-Display P3.
האפליקציה יכולה לשלוח שאילתה על מרחב הצבעים של מפת סיביות באמצעות קריאה
getColorSpace()
כדי לקבוע אם המערכת מזהה מרחב צבעים ספציפי כמרחב צבעים רחב, אפשר להפעיל את השיטה isWideGamut()
.
המחלקה Color
מאפשרת לייצג צבע עם ארבעה רכיבים
דחוסים בערך ארוך של 64 ביט, במקום הייצוג הנפוץ ביותר שמשתמש במספר שלם
עם ערך מסוים. בעזרת ערכים ארוכים אפשר להגדיר צבעים בצורה מדויקת יותר מאשר בעזרת ערכים שלמים. אם צריך ליצור או לקודד צבע כערך long, משתמשים באחת מהשיטות pack()
בכיתה Color
.
כדי לוודא שהאפליקציה שלכם ביקשה כראוי את מצב הצבעים הרחב, עליכם לבדוק שה-method getColorMode()
מחזיר את הערך COLOR_MODE_WIDE_COLOR_GAMUT
(עם זאת, ה-method הזה לא מציין אם מצב הצבעים הרחב אושר בפועל).
שימוש בערכת צבעים רחבה בקוד מקורי
בקטע הזה נסביר איך להפעיל מצב של סולם צבעים רחב באמצעות OpenGL ממשקי API של Vulkan אם האפליקציה שלכם משתמשת בקוד נייטיב.
OpenGL
כדי להשתמש במצב מטווח צבעים רחב ב-OpenGL, צריך לכלול באפליקציה את ספריית EGL 1.4 עם אחד מהתוספים הבאים:
כדי להפעיל את התכונה, קודם צריך ליצור הקשר GL באמצעות eglChooseConfig
, עם אחד משלושת הפורמטים הנתמכים של מאגרי צבע לצבע רחב במאפיינים. פורמט מאגר הצבע לצבע רחב חייב להיות אחת מהקבוצות הבאות של ערכי RGBA:
- 8, 8, 8, 8
- 10, 10, 10, 2
- FP16, FP16, FP16, FP16
לאחר מכן, מבקשים את תוסף מרחב הצבעים P3 כשיוצרים את לעבד יעדים, כפי שמוצג בקטע הקוד הבא:
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
התמיכה של Vulkan במערך צבעים רחב מסופקת באמצעות
התוסף VK_EXT_swapchain_colorspace
.
לפני שמפעילים תמיכה בצבעים רחבים בקוד Vulkan, צריך קודם לבדוק אם התוסף נתמך באמצעות vkEnumerateInstanceExtensionProperties
.
אם התוסף זמין, צריך להפעיל אותו במהלך
vkCreateInstance
לפני שיוצרים תמונות החלפה שמותאמות
להשתמש במרחבי הצבע הנוספים שהתוסף מגדיר.
לפני יצירת ההחלפה, עליך לבחור את מרחב הצבעים הרצוי, ואז לעבור על את הפלטפורמות הזמינות של מכשירים פיזיים ולבחור בשבילם פורמט צבע תקין מרחב צבעים.
במכשירי Android, ב-Vulkan יש תמיכה במערך צבעים רחב עם מרחבי הצבעים הבאים וגם
VkSurfaceFormatKHR
פורמטים של צבעים:
- מרחבי צבעים רחבים של Vulkan עם סולם צבעים:
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
- פורמטים של צבע ב-Vulkan עם תמיכה בטווח רחב של צבעים:
VK_FORMAT_R16G16B16A16_SFLOAT
VK_FORMAT_A2R10G10B10_UNORM_PACK32
VK_FORMAT_R8G8B8A8_UNORM
קטע הקוד הבא מראה איך אפשר לבדוק אם המכשיר תומך בטכנולוגיית 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 }
קטע הקוד הבא מראה איך לבקש החלפה של Vulkan עם
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; }