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

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

فهم وضع نطاق الألوان الواسع

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

على أجهزة Android التي تعمل بالإصدار 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث المتوافقة مع هذه الميزة، يمكن لتطبيقك تفعيل وضع الألوان ذات النطاق الواسع لنشاط معيّن، ما يتيح للنظام التعرّف على صور الخطوط المسطّحة ومعالجتها بشكلٍ صحيح باستخدام ملفات تعريف الألوان ذات النطاق الواسع المضمّنة. تشير رسالة الأشكال البيانية تضم الفئة ColorSpace.Named قائمة جزئية من الفئات الشائعة الاستخدام. ومساحات الألوان التي يدعمها Android.

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

تفعيل وضع نطاق الألوان الواسع

استخدِم السمة colorMode لطلب عرض النشاط. في وضع مجموعة الألوان الواسعة على الأجهزة المتوافقة في وضع مجموعة الألوان الواسعة، يمكن عرض نافذة خارج سلسلة sRGB لعرض ألوان أكثر حيوية. إذا كان الجهاز لا يتيح عرض الألوان العريضة النطاق، لن يكون لهذه السمة أي تأثير. إذا كان تطبيقك بحاجة إلى تحديد ما إذا كانت صورة الشاشة قادرة على توسيع نطاق الألوان، اتصل طريقة isWideColorGamut(). يمكن لتطبيقك أيضًا استدعاء دالة isScreenWideColorGamut() التي تعرض القيمة true فقط إذا كانت الشاشة قادرة على عرض مجموعة ألوان واسعة وكان الجهاز متوافقًا مع ميزة عرض الألوان باستخدام مجموعة ألوان واسعة.

قد تكون الشاشة قادرة على عرض نطاق ألوان واسع ولكن لا تتيح إدارة الألوان، وفي هذه الحالة، لن يمنح النظام التطبيق وضع نطاق الألوان الواسع. عندما تكون الشاشة غير مُدارة بالألوان —كما كان الحال مع جميع إصدارات Android التي تسبق الإصدار 8.0 — يعيد النظام تعيين الألوان التي يرسمها التطبيق إلى سلسلة الشاشة.

لتفعيل مجموعة الألوان الواسعة في نشاطك، عليك ضبط colorMode. إلى wideColorGamut في ملف AndroidManifest.xml. عليك تنفيذ ذلك لكل نشاط تريد تفعيل وضع الألوان الواسعة له.

android:colorMode="wideColorGamut"

يمكنك أيضًا ضبط وضع الألوان آليًا في نشاطك من خلال طلب طريقة واحدة (setColorMode(int)) وتمريرها COLOR_MODE_WIDE_COLOR_GAMUT

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

الشكل 1. مساحات ألوان Display 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 تنسيقات الألوان:

  • مساحات ألوان النطاق اللوني الواسع في 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

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