تحسين الرسومات باستخدام ألوان عريضة

قدّم إصدار Android 8.0 (مستوى واجهة برمجة التطبيقات 26) دعمًا لإدارة الألوان للحصول على مسافات اللون إلى جانب النموذج اللوني أحمر أخضر أزرق (sRGB) عادي لعرض الرسومات على الأجهزة ذات الشاشات المتوافقة. من خلال هذا الدعم، يمكن لتطبيقك عرض صور نقطية مع ملفات تعريف ألوان واسعة مضمَّنة يتم تحميلها من ملفات PNG وJPEG وWebP. عبر جافا أو رمز أصلي. يمكن للتطبيقات التي تستخدم OpenGL أو Vulkan إنتاج مجموعة ألوان واسعة مباشرةً (باستخدام الشاشة P3 scRGB). هذه الإمكانية مفيدًا لإنشاء تطبيقات تتضمّن عمليات إعادة إنتاج عالية الدقة للألوان، مثل الصور والفيديوهات تطبيقات التعديل.

التعرّف على وضع مجموعة الألوان الواسعة

ملفات تعريف الألوان الواسعة ملفات ICC، مثل Adobe RGB Pro Photo RGB DCI-P3، وهي قادر على تمثيل مجموعة ألوان أكبر من sRGB. الشاشات التي تدعم الملفات الشخصية للألوان العريضة من خلال عرض صور بألوان أساسية أكثر عمقًا (الأحمر والأخضر والأزرق) بالإضافة إلى عرض صور ثانوية أكثر ثراءً الألوان (مثل الأحمر الأرجواني والأزرق السماوي والأصفر).

بالنسبة إلى أجهزة Android التي تعمل بالإصدار 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث من نظام التشغيل Android، يمكن لتطبيقك تنفيذ ما يلي: تفعيل وضع ألوان مجموعة الألوان الواسعة لنشاط يتعرّف فيه النظام على معالجة الصور النقطية بشكل صحيح مع ملفات تعريف ألوان واسعة مضمَّنة. تشير رسالة الأشكال البيانية تضم الفئة 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

عرض محتوى نطاق ألوان عريض

الشكل 1. الشاشة P3 (البرتقالي) مقابل مساحات اللون sRGB (البيضاء)

لعرض محتوى واسع النطاق، يجب أن يحمِّل تطبيقك صورة نقطية واسعة اللون، وتكون صورة نقطية ملف تعريف لوني يحتوي على مساحة لون أعرض من sRGB. تتضمن الملفات الشخصية للألوان الواسعة الشائعة Adobe RGB وDCI-P3 وDisplay P3

يمكن لتطبيقك الاستعلام عن مساحة اللون لصورة نقطية، من خلال استدعاء getColorSpace() لتحديد ما إذا كان النظام يتعرف على مساحة لون محددة لتكون مجموعة واسعة، يمكنك استدعاء طريقة isWideGamut().

تتيح لك الفئة Color تمثيل لون بأربعة مكونات معبأة في قيمة طويلة 64 بت، بدلاً من التمثيل الأكثر شيوعًا الذي يستخدم عددًا صحيحًا باستخدام القيم الطويلة، يمكنك تحديد الألوان باستخدام دقة أكبر من قيم الأعداد الصحيحة. إذا كنت بحاجة إلى إنشاء أو ترميز لون كقيمة طويلة، استخدم باستخدام إحدى طرق pack() في الفئة Color.

يمكنك التحقّق مما إذا كان تطبيقك قد طلب بشكل صحيح وضع مجموعة الألوان الواسعة من خلال التحقّق من ذلك. تُرجع الطريقة getColorMode() COLOR_MODE_WIDE_COLOR_GAMUT (لا تشير هذه الطريقة إلى مع ذلك، ما إذا كان قد تم منح وضع مجموعة الألوان الواسعة أم لا).

استخدام إمكانية استخدام مجموعة ألوان واسعة في الرموز البرمجية الأصلية

يصف هذا القسم كيفية تمكين وضع مجموعة الألوان الواسعة من خلال OpenGL واجهات برمجة تطبيقات 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 لمجموعة الألوان الواسعة من خلال الإضافة "VK_EXT_swapchain_colorspace".

قبل تفعيل إمكانية استخدام الألوان العريضة في رمز Vulkan، تأكَّد أولاً من أنّ يتم دعم الإضافة عبر vkEnumerateInstanceExtensionProperties إذا كانت الإضافة متاحة، يجب تفعيلها أثناء vkCreateInstance قبل إنشاء أي صور لسلسلة التبديل التي تستخدم مساحات اللون الإضافية المحددة بواسطة الإضافة.

وقبل إنشاء سلسلة التبديل، عليك اختيار مساحة اللون المطلوبة، ثم الانتقال إلى مساحات العرض المتوفّرة للأجهزة الفعلية واختَر تنسيق ألوان صالحًا لذلك مساحة اللون.

على أجهزة Android، يدعم Vulkan مجموعة ألوان واسعة مع مساحات الألوان VkSurfaceFormatKHR تنسيقات الألوان:

  • مساحات ألوان Sense واسعة النطاق:
    • VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
    • VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
  • تنسيقات ألوان Sense مع إتاحة مجموعة ألوان واسعة:
    • VK_FORMAT_R16G16B16A16_SFLOAT
    • VK_FORMAT_A2R10G10B10_UNORM_PACK32
    • VK_FORMAT_R8G8B8A8_UNORM

يوضح مقتطف الرمز التالي كيفية التحقق من أن الجهاز يتوافق مع شاشة العرض 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;
}