گرافیک را با محتوای رنگی گسترده تقویت کنید

اندروید 8.0 (سطح API 26) پشتیبانی مدیریت رنگ را برای فضاهای رنگی اضافی در کنار استاندارد RGB (sRGB) برای رندر کردن گرافیک در دستگاه‌های دارای نمایشگر سازگار معرفی کرد. با این پشتیبانی، برنامه شما می‌تواند نقشه‌های بیتی را با نمایه‌های رنگی گسترده تعبیه‌شده بارگیری شده از فایل‌های PNG، JPEG و WebP از طریق جاوا یا کد بومی ارائه کند. برنامه‌هایی که از OpenGL یا Vulkan استفاده می‌کنند می‌توانند مستقیماً محتوای رنگی گسترده (با استفاده از Display P3 و scRGB ) تولید کنند. این قابلیت برای ایجاد برنامه هایی که شامل بازتولید رنگ با کیفیت بالا هستند، مانند برنامه های ویرایش تصویر و ویدیو مفید است.

حالت طیف رنگ گسترده را درک کنید

نمایه‌های رنگی گسترده، پروفایل‌های ICC ، مانند Adobe RGB ، Pro Photo RGB ، و DCI-P3 هستند که می‌توانند طیف وسیع‌تری از رنگ‌ها را نسبت به sRGB نشان دهند. صفحه نمایش هایی که از پروفایل های رنگی گسترده پشتیبانی می کنند می توانند تصاویر را با رنگ های اصلی عمیق تر (قرمز، سبز و آبی) و همچنین رنگ های ثانویه غنی تر (مانند سرخابی، فیروزه ای و زرد) نمایش دهند.

در دستگاه‌های Android دارای Android 8.0 (سطح API 26) یا بالاتر که از آن پشتیبانی می‌کنند، برنامه شما می‌تواند حالت رنگ طیف گسترده‌ای را برای فعالیتی فعال کند که به موجب آن سیستم تصاویر بیت مپ را با نمایه‌های رنگ گسترده تعبیه‌شده تشخیص داده و به درستی پردازش می‌کند. کلاس ColorSpace.Named فهرستی جزئی از فضاهای رنگی رایج را که اندروید پشتیبانی می‌کند، برمی‌شمارد.

توجه: هنگامی که حالت طیف رنگ گسترده فعال است، پنجره فعالیت از حافظه و پردازش GPU بیشتری برای ترکیب صفحه استفاده می کند. قبل از فعال کردن حالت طیف رنگ گسترده، باید به دقت بررسی کنید که آیا فعالیت واقعاً از آن سود می برد یا خیر. به عنوان مثال، فعالیتی که عکس ها را به صورت تمام صفحه نمایش می دهد، کاندیدای خوبی برای حالت طیف رنگی گسترده است، اما فعالیتی که تصاویر کوچک کوچک را نشان می دهد، اینطور نیست.

حالت طیف رنگ گسترده را فعال کنید

از ویژگی colorMode برای درخواست نمایش فعالیت در حالت طیف رنگی گسترده در دستگاه‌های سازگار استفاده کنید. در حالت وسعت رنگ گسترده، یک پنجره می‌تواند خارج از محدوده sRGB نمایش داده شود تا رنگ‌های زنده‌تر را نمایش دهد. اگر دستگاه از رندر طیف رنگی گسترده پشتیبانی نمی کند، این ویژگی تأثیری ندارد. اگر برنامه شما باید تعیین کند که آیا یک صفحه نمایش داده شده دارای طیف رنگ گسترده است یا خیر، متد isWideColorGamut() را فراخوانی کنید. برنامه همچنین می‌تواند isScreenWideColorGamut() را فراخوانی کند، که فقط در صورتی که صفحه نمایش دارای وسعت رنگ گسترده باشد و دستگاه از رندر رنگی گسترده پشتیبانی کند true برمی‌گردد.

نمایشگر ممکن است دارای وسعت رنگ گسترده باشد اما مدیریت رنگ نداشته باشد، در این صورت، سیستم حالت وسعت رنگ گسترده را به برنامه نمی دهد. هنگامی که نمایشگر با رنگ مدیریت نمی شود - مانند همه نسخه های اندروید قبل از نسخه 8.0 - سیستم رنگ های ترسیم شده توسط برنامه را به وسعت نمایشگر تغییر می دهد.

برای فعال کردن وسعت رنگ گسترده در فعالیت خود، ویژگی colorMode را در فایل AndroidManifest.xml خود روی wideColorGamut تنظیم کنید. شما باید این کار را برای هر فعالیتی که می خواهید حالت رنگ گسترده را برای آن فعال کنید، انجام دهید.

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 را برمی گرداند، می توانید بررسی کنید که آیا برنامه شما به درستی حالت وسعت رنگ گسترده را درخواست کرده است یا خیر (اما این روش نشان نمی دهد که آیا حالت وسعت رنگ گسترده واقعاً اعطا شده است یا خیر).

از پشتیبانی طیف رنگی گسترده در کدهای بومی استفاده کنید

اگر برنامه شما از کد بومی استفاده می‌کند، این بخش نحوه فعال کردن حالت طیف رنگی گسترده با APIهای 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 قبل از ایجاد هر گونه تصویر swapchain که از فضاهای رنگ اضافی تعریف شده توسط برنامه افزودنی استفاده می کند، فعال کنید.

قبل از ایجاد swapchain، باید فضای رنگی مورد نظر خود را انتخاب کنید، سپس سطوح دستگاه فیزیکی موجود را حلقه بزنید و یک قالب رنگ معتبر برای آن فضای رنگی انتخاب کنید.

در دستگاه‌های 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
}

قطعه کد زیر نحوه درخواست swapchain 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;
}