Поддержка JPEG YCbCr
Начиная с Windows 8.1, кодек JPEG компонента изображений Windows (WIC) поддерживает чтение и запись данных изображений в собственной форме YCbCr. Поддержку WIC YCbCr можно использовать в сочетании с Direct2D для отрисовки пиксельных данных YCbCr с эффектом изображения. Кроме того, кодек WIC JPEG может использовать пиксельные данные YCbCr , созданные определенными драйверами камеры через Media Foundation.
Данные пикселей YCbCR потребляют значительно меньше памяти, чем стандартные форматы пикселей BGRA. Кроме того, доступ к данным YCbCR позволяет разгрузить некоторые этапы конвейера декодирования и кодирования JPEG в Direct2D с ускорением GPU. С помощью YCbCr ваше приложение может сократить потребление памяти JPEG и время загрузки для изображений того же размера и качества. Кроме того, приложение может использовать изображения JPEG с более высоким разрешением без снижения производительности.
В этом разделе описывается, как работают данные YCbCr и как их использовать в WIC и Direct2D.
- Сведения о данных JPEG YCbCr
-
Использование данных JPEG YCbCr
- Использование изображений YCbCr JPEG
- API-интерфейсы компонентов обработки образов Windows
- API Direct2D
- Определение поддержки конфигурации YCbCr
- Декодирование пиксельных данных YCbCr
- Преобразование пиксельных данных YCbCr
- Кодирование пиксельных данных YCbCr
- Декодирование пиксельных данных YCbCR в Windows 10
- Связанные темы
В этом разделе описываются некоторые ключевые понятия, необходимые для понимания того, как работает поддержка YCbCr в WIC и ее основные преимущества.
WIC в Windows 8 и более ранних версиях поддерживает четыре различные цветовые модели, наиболее распространенной из которых является RGB/BGR. Эта цветовая модель определяет цветовые данные с помощью компонентов красного, зеленого и синего цветов; также можно использовать четвертый альфа-компонент.
Вот изображение, разложенное на красный, зеленый и синий компоненты.
YCbCr — это альтернативная цветовая модель, которая определяет цветовые данные с помощью компонента яркости (Y) и двух компонентов хрома (Cb и Cr). Обычно используется в сценариях создания цифровых изображений и видео. Термин YCbCr часто используется взаимозаменяемо с YUV, хотя они технически различаются.
Существует несколько вариантов YCbCr , которые отличаются цветовым пространством и определениями динамических диапазонов. WIC, в частности, поддерживает данные JPEG JFIF YCbCr . Дополнительные сведения см. в спецификации JPEG ITU-T81.
Ниже приведен образ, разделенный на компоненты Y, Cb и Cr .
В этом разделе описываются некоторые различия между доступом к данным пикселей RGB и их хранением в памяти и данными YCbCR .
Данные в пикселях RGB обычно хранятся с помощью макета памяти с чередованием. Это означает, что данные для одного компонента цвета чередуются между пикселями, и каждый пиксель хранится непрерывно в памяти.
Ниже приведен рисунок, показывающий пиксельные данные RGBA, хранящиеся в макете памяти с чередованием.
Данные YCbCR обычно хранятся с помощью макета планарной памяти. Это означает, что каждый компонент цвета хранится отдельно в отдельной смежных плоскостях, в общей сложности для трех плоскостей. В другой распространенной конфигурации компоненты Cb и Cr чередуются и хранятся вместе, а компонент Y остается в собственной плоскости, в общей сложности для двух плоскостей.
Вот рисунок, показывающий плоской Y и чередование данных пикселей CbCr , общий макет памяти YCbCr .
В WIC и Direct2D каждая цветовая плоскость рассматривается как собственный отдельный объект ( IWICBitmapSource или ID2D1Bitmap), и вместе эти плоскости формируют резервные данные для изображения YCbCr .
Хотя WIC поддерживает доступ к данным YCbCr в конфигурациях плоскости 2 и 3, Direct2D поддерживает только первые (Y и CbCR). Поэтому при совместном использовании WIC и Direct2D всегда следует использовать конфигурацию YCbCR 2 плоскости.
Цветовая модель YCbCR хорошо подходит для сценариев создания цифровых изображений, так как она может использовать определенные аспекты визуальной системы человека. В частности, люди более чувствительны к изменениям яркости (яркости) изображения и менее чувствительны к хрома (цвету). Разделив данные о цвете на отдельные компоненты яркости и хрома, мы можем выборочно сжать только компоненты хрома, чтобы добиться экономии пространства с минимальной потерей качества.
Один из методов для этого называется chroma subsampling. Плоскости Cb и Cr имеют подвыбранные (пониженные масштабы) в одном или обоих горизонтальных и вертикальных измерениях. По историческим причинам каждый режим chroma subsampling обычно называется с использованием трехкомпонентного соотношения J:a:b.
Режим подсэмплинга | Горизонтальное уменьшение масштаба | Вертикальное уменьшение масштаба | Бит на пиксель* |
---|---|---|---|
4:4:4 | 1x | 1x | 24 |
4:2:2 | 2x | 1x | 16 |
4:4:0 | 1x | 2x | 16 |
4:2:0 | 2x | 2x | 12 |
* Включает данные Y.
Из приведенной выше таблицы при использовании YCbCR для хранения несжатых данных изображений можно добиться экономии памяти от 25 % до 62,5 % по сравнению с 32 битами данных RGBA на пиксель в зависимости от того, какой режим хрома используется.
На высоком уровне конвейер распаковки JPEG состоит из следующих этапов:
- Выполнение распаковки энтропии (например, Хаффман)
- Выполнение деквантизации
- Выполнение обратного дискретного преобразования косисинуса
- Выполнение chroma upsampling для данных CbCR
- Преобразование данных YCbCr в RGBA (при необходимости)
Если кодек JPEG создает данные YCbCr , мы можем избежать последних двух этапов процесса декодирования или отложить их на GPU. В дополнение к экономии памяти, указанной в предыдущем разделе, это значительно сокращает общее время, необходимое для декодирования изображения. Та же экономия применяется при кодировании данных YCbCr .
В этом разделе объясняется, как использовать WIC и Direct2D для работы с данными YCbCR .
Инструкции из этого документа, используемые на практике, см. в примере оптимизации YCbCr JPEG в Direct2D и WIC , в котором показаны все шаги, необходимые для декодирования и отрисовки содержимого YCbCr в приложении Direct2D.
Подавляющее большинство изображений JPEG хранятся в формате YCbCr. Некоторые JPEG содержат данные CMYK или оттенков серого и не используют YCbCr. Это означает, что обычно, но не всегда, можно напрямую использовать уже существующее содержимое JPEG без каких-либо изменений.
WIC и Direct2D не поддерживают все возможные конфигурации YCbCr , а поддержка YCbCr в Direct2D зависит от базового графического оборудования и драйвера. По этой причине конвейер создания образов общего назначения должен быть надежным для образов, которые не используют YCbCr (включая другие распространенные форматы изображений, такие как PNG или BMP), или в случаях, когда поддержка YCbCr недоступна. Рекомендуется сохранить существующий конвейер образов на основе BGRA и включить YCbCr в качестве оптимизации производительности, если он доступен.
WIC в Windows 8.1 добавляет три новых интерфейса для предоставления доступа к данным JPEG YCbCr.
IWICPlanarBitmapSourceTransform аналогичен IWICBitmapSourceTransform, за исключением того, что он создает пиксели в плоскостной конфигурации, включая данные YCbCr . Этот интерфейс можно получить, вызвав QueryInterface в реализации IWICBitmapSource , которая поддерживает планарный доступ. Сюда входит реализация кодека JPEG для IWICBitmapFrameDecode , а также IWICBitmapScaler, IWICBitmapFlipRotator и IWICColorTransform.
IWICPlanarBitmapFrameEncode предоставляет возможность кодировать плоские пиксельные данные, включая данные YCbCr . Этот интерфейс можно получить, вызвав QueryInterface в реализации кодека JPEG IWICBitmapFrameEncode.
IWICPlanarFormatConverter позволяет IWICFormatConverter использовать плоские пиксельные данные, включая YCbCr, и преобразовать их в формат с чередованием пикселей. Он не предоставляет возможность преобразования данных с чередованием пикселей в плоской формат. Этот интерфейс можно получить, вызвав QueryInterface в предоставленной Windows реализации IWICFormatConverter.
Direct2D в Windows 8.1 поддерживает YCbCr плоский пиксель данных с новым эффектом изображения YCbCr . Этот эффект обеспечивает возможность отрисовки данных YCbCr . Эффект принимает в качестве входных данных два интерфейса ID2D1Bitmap : один из них содержит планарные данные Y в формате DXGI_FORMAT_R8_UNORM, а другой — чередующиеся данные CbCr в формате DXGI_FORMAT_R8G8_UNORM. Обычно этот эффект используется вместо ID2D1Bitmap , который содержал бы пиксельные данные BGRA.
Эффект изображения YCbCr предназначен для использования в сочетании с API WIC YCbCr , которые предоставляют данные YCbCr . Это эффективно действует для разгрузки некоторых операций декодирования с ЦП на GPU, где их можно обрабатывать гораздо быстрее и в параллельном режиме.
Как отмечалось ранее, ваше приложение должно быть надежным в тех случаях, когда поддержка YCbCr недоступна. В этом разделе рассматриваются условия, для которых приложение должно проверка. Если какая-либо из следующих проверок не пройдена, приложение должно вернуться к стандартному конвейеру на основе BGRA.
Доступ к данным YCbCR поддерживают только кодек JPEG, предоставленный Windows, и некоторые преобразования WIC. Полный список см. в разделе Api-интерфейсы компонентов обработки образов Windows .
Чтобы получить один из плоских интерфейсов YCbCr , вызовите QueryInterface в исходном интерфейсе. Это приведет к сбою, если компонент не поддерживает доступ к данным YCbCR .
После получения IWICPlanarBitmapSourceTransform необходимо сначала вызвать DoesSupportTransform. Этот метод принимает в качестве входных параметров полный набор преобразований, которые необходимо применить к данным плоских YCbCr , и возвращает логическое значение, указывающее на поддержку, а также ближайшие измерения к запрошенным размерам, которые могут быть возвращены. Перед доступом к пиксельным данным следует проверка все три значения с помощью IWICPlanarBitmapSourceTransform::CopyPixels.
Этот шаблон аналогичен использованию IWICBitmapSourceTransform .
Это проверка необходимо только в том случае, если вы используете эффект Direct2D YCbCr для отрисовки содержимого YCbCr. Direct2D хранит данные YCbCR с использованием форматов DXGI_FORMAT_R8_UNORM и DXGI_FORMAT_R8G8_UNORM пикселей, которые доступны не во всех графических драйверах.
Перед использованием эффекта изображения YCbCr необходимо вызвать ID2D1DeviceContext::IsDxgiFormatSupported , чтобы убедиться, что драйвер поддерживает оба формата.
Ниже приведен пример кода, демонстрирующий рекомендуемые проверки. Этот пример взят из оптимизаций JPEG YCbCr в примере Direct2D и WIC.
bool DirectXSampleRenderer::DoesWicSupportRequestedYCbCr()
{
ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
HRESULT hr = m_wicScaler.As(&wicPlanarSource);
if (SUCCEEDED(hr))
{
BOOL isTransformSupported;
uint32 supportedWidth = m_cachedBitmapPixelWidth;
uint32 supportedHeight = m_cachedBitmapPixelHeight;
DX::ThrowIfFailed(
wicPlanarSource->DoesSupportTransform(
&supportedWidth,
&supportedHeight,
WICBitmapTransformRotate0,
WICPlanarOptionsDefault,
SampleConstants::WicYCbCrFormats,
m_planeDescriptions,
SampleConstants::NumPlanes,
&isTransformSupported
)
);
// The returned width and height may be larger if IWICPlanarBitmapSourceTransform does not
// exactly support what is requested.
if ((isTransformSupported == TRUE) &&
(supportedWidth == m_cachedBitmapPixelWidth) &&
(supportedHeight == m_cachedBitmapPixelHeight))
{
return true;
}
}
return false;
}
bool DirectXSampleRenderer::DoesDriverSupportYCbCr()
{
auto d2dContext = m_deviceResources->GetD2DDeviceContext();
return (d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8_UNORM)) &&
(d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8G8_UNORM));
}
Если вы хотите получить пиксельные данные YCbCr, следует вызвать IWICPlanarBitmapSourceTransform::CopyPixels. Этот метод копирует пиксельные данные в массив заполненных структур WICBitmapPlane , по одному для каждой плоскости данных (например, Y и CbCR). WICBitmapPlane содержит сведения о пиксельных данных и указывает на буфер памяти, который будет получать данные.
Если вы хотите использовать пиксельные данные YCbCr с другими API WIC, создайте правильно настроенный IWICBitmap, вызовите Lock , чтобы получить базовый буфер памяти, и свяжите буфер с WICBitmapPlane, используемым для получения пиксельных данных YCbCr . Затем можно использовать IWICBitmap в обычном режиме.
Наконец, если вы хотите отобразить данные YCbCr в Direct2D, следует создать ID2D1Bitmap из каждого IWICBitmap и использовать их в качестве источника для эффекта изображения YCbCr . WIC позволяет запрашивать несколько планарных конфигураций. При взаимодействии с Direct2D следует запрашивать две плоскости, одна из них использует GUID_WICPixelFormat8bppY, а другая — GUID_WICPixelFormat16bppCbCr, так как это конфигурация, ожидаемая в Direct2D.
Ниже приведен пример кода, демонстрирующий шаги по декодированию и отрисовке данных YCbCr в Direct2D. Этот пример взят из оптимизаций JPEG YCbCr в примере Direct2D и WIC.
void DirectXSampleRenderer::CreateYCbCrDeviceResources()
{
auto wicFactory = m_deviceResources->GetWicImagingFactory();
auto d2dContext = m_deviceResources->GetD2DDeviceContext();
ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
DX::ThrowIfFailed(
m_wicScaler.As(&wicPlanarSource)
);
ComPtr<IWICBitmap> bitmaps[SampleConstants::NumPlanes];
ComPtr<IWICBitmapLock> locks[SampleConstants::NumPlanes];
WICBitmapPlane planes[SampleConstants::NumPlanes];
for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
{
DX::ThrowIfFailed(
wicFactory->CreateBitmap(
m_planeDescriptions[i].Width,
m_planeDescriptions[i].Height,
m_planeDescriptions[i].Format,
WICBitmapCacheOnLoad,
&bitmaps[i]
)
);
LockBitmap(bitmaps[i].Get(), WICBitmapLockWrite, nullptr, &locks[i], &planes[i]);
}
DX::ThrowIfFailed(
wicPlanarSource->CopyPixels(
nullptr, // Copy the entire source region.
m_cachedBitmapPixelWidth,
m_cachedBitmapPixelHeight,
WICBitmapTransformRotate0,
WICPlanarOptionsDefault,
planes,
SampleConstants::NumPlanes
)
);
DX::ThrowIfFailed(d2dContext->CreateEffect(CLSID_D2D1YCbCr, &m_d2dYCbCrEffect));
ComPtr<ID2D1Bitmap1> d2dBitmaps[SampleConstants::NumPlanes];
for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
{
// IWICBitmapLock must be released before using the IWICBitmap.
locks[i] = nullptr;
// First ID2D1Bitmap1 is DXGI_FORMAT_R8 (Y), second is DXGI_FORMAT_R8G8 (CbCr).
DX::ThrowIfFailed(d2dContext->CreateBitmapFromWicBitmap(bitmaps[i].Get(), &d2dBitmaps[i]));
m_d2dYCbCrEffect->SetInput(i, d2dBitmaps[i].Get());
}
}
void DirectXSampleRenderer::LockBitmap(
_In_ IWICBitmap *pBitmap,
DWORD bitmapLockFlags,
_In_opt_ const WICRect *prcSource,
_Outptr_ IWICBitmapLock **ppBitmapLock,
_Out_ WICBitmapPlane *pPlane
)
{
// ComPtr guarantees the IWICBitmapLock is released if an exception is thrown.
ComPtr<IWICBitmapLock> lock;
DX::ThrowIfFailed(pBitmap->Lock(prcSource, bitmapLockFlags, &lock));
DX::ThrowIfFailed(lock->GetStride(&pPlane->cbStride));
DX::ThrowIfFailed(lock->GetDataPointer(&pPlane->cbBufferSize, &pPlane->pbBuffer));
DX::ThrowIfFailed(lock->GetPixelFormat(&pPlane->Format));
*ppBitmapLock = lock.Detach();
}
Преобразование данных YCbCr почти идентично декодированию, так как оба они связаны с IWICPlanarBitmapSourceTransform. Единственное различие заключается в том, из какого объекта WIC вы получили интерфейс. В Windows предусмотрено средство масштабирования, вращатель переворачивания и преобразование цвета, поддерживается доступ YCbCr .
WIC поддерживает концепцию объединения нескольких преобразований. Например, можно создать следующий конвейер WIC:
Затем можно вызвать QueryInterface в IWICColorTransform , чтобы получить IWICPlanarBitmapSourceTransform. Преобразование цвета может взаимодействовать с предыдущими преобразованиями и может предоставлять статистические возможности каждого этапа конвейера. WIC гарантирует, что данные YCbCR сохраняются в течение всего процесса. Эта цепочка работает только при использовании компонентов, поддерживающих доступ YCbCr .
Подобно реализации декодирования кадров JPEG в IWICBitmapSourceTransform, реализация декодирования кадров JPEG для IWICPlanarBitmapSourceTransform поддерживает масштабирование и поворот собственного домена JPEG DCT. Вы можете запросить мощность на два уменьшения масштаба или поворот непосредственно из декодера JPEG. Обычно это приводит к более высокому качеству и производительности, чем при использовании дискретных преобразований.
Кроме того, при связывании одного или нескольких преобразований WIC после декодера JPEG он может использовать собственное масштабирование и поворот JPEG для удовлетворения запрошенной статистической операции.
Используйте IWICPlanarFormatConverter для преобразования плоских данных пикселей YCbCr в формат с чередованием пикселей, например GUID_WICPixelFormat32bppPBGRA. WIC в Windows 8.1 не предоставляет возможность преобразования в плоской формат пикселей YCbCr.
Используйте IWICPlanarBitmapFrameEncode для кодирования данных пикселей YCbCr в кодировщике JPEG. Кодирование данных YCbCrIWICPlanarBitmapFrameEncode аналогично кодированию данных с чередованием с помощью IWICBitmapFrameEncode. Планарный интерфейс предоставляет только возможность записи данных изображения плоских кадров, и следует продолжать использовать интерфейс кодирования кадров для задания метаданных или эскиза и фиксации в конце операции.
В типичном случае необходимо выполнить следующие действия.
- Получите IWICBitmapFrameEncode в обычном режиме. Если вы хотите настроить подвыборку хрома, задайте параметр кодировщика JpegYCrCbSubsampling при создании кадра.
- Если вам нужно задать метаданные или эскиз, сделайте это с помощью IWICBitmapFrameEncode в обычном режиме.
- QueryInterface для IWICPlanarBitmapFrameEncode.
- Задайте пиксельные данные YCbCr с помощью IWICPlanarBitmapFrameEncode::WriteSource или IWICPlanarBitmapFrameEncode::WritePixels. В отличие от своих аналогов IWICBitmapFrameEncode , эти методы предоставляются с массивом IWICBitmapSource или WICBitmapPlane , который содержит плоскости пикселей YCbCr .
- По завершении вызовите IWICBitmapFrameEncode::Commit.
Начиная с Windows 10 сборки 1507, Direct2D предоставляет ID2D1ImageSourceFromWic, более простой способ декодирования JPEG в Direct2D с использованием оптимизации YCbCr. ID2D1ImageSourceFromWic автоматически выполняет все необходимые проверки возможностей YCbCr ; по возможности используется оптимизированный путь к коду, а в противном случае используется резервный путь. Он также позволяет выполнять новые оптимизации, такие как кэширование только подобласти изображения, которые требуются в данный момент времени.
Дополнительные сведения об использовании ID2D1ImageSourceFromWic см. в примере пакета SDK для Direct2D Photo Adjustment.