Реализация IWICBitmapDecoder

IWICBitmapDecoder

Когда приложение запрашивает декодер, первой точкой взаимодействия с кодеком является интерфейс IWICBitmapDecoder . Это интерфейс уровня контейнера, который предоставляет доступ к свойствам верхнего уровня контейнера и, что самое главное, к кадрам, которые он содержит. Это основной интерфейс в классе декодера уровня контейнера.

interface IWICBitmapDecoder : IUnknown
{
// Required methods
   HRESULT QueryCapability (IStream *pIStream, 
      DWORD *pdwCapabilities );
   HRESULT Initialize ( IStream *pIStream,
      WICDecodeOptions cacheOptions );
   HRESULT GetContainerFormat ( GUID *pguidContainerFormat );
   HRESULT GetDecoderInfo ( IWICBitmapDecoderInfo **pIDecoderInfo );
   HRESULT GetFrameCount ( UINT *pCount );
   HRESULT GetFrame ( UINT index, 
      IWICBitmapFrameDecode **ppIBitmapFrame );

// Optional methods
   HRESULT GetPreview ( IWICBitmapSource **ppIPreview );
   HRESULT GetThumbnail ( IWICBitmapSource **ppIThumbnail );
   HRESULT GetColorContexts ( UINT cCount, 
      IWICColorContext **ppIColorContexts, 
      UINT *pcActualCount );
   HRESULT GetMetadataQueryReader ( IWICMetadataQueryReader **ppIMetadataQueryReader);
   HRESULT CopyPalette ( IWICPalette *pIPalette );
}

Некоторые форматы изображений имеют глобальные эскизы, контексты цвета или метаданные, в то время как многие форматы изображений предоставляют их только для каждого кадра. Методы для доступа к этим элементам являются необязательными в IWICBitmapDecoder, но являются обязательными для IWICBitmapFrameDecode. Аналогичным образом, некоторые кодеки не используют индексированные форматы пикселей и поэтому не нужно реализовывать методы CopyPalette в любом из интерфейсов. Дополнительные сведения о необязательных методах IWICBitmapDecoder см. в разделе Реализация IWICBitmapFrameDecode, где они чаще всего реализуются.

QueryCapability

QueryCapability — это метод, используемый для арбитража кодека. (См. раздел Обнаружение и арбитраж в разделе How The Windows Imaging Component Works (Как работает компонент обработки изображений Windows ).) Если два кодека способны декодировать один и тот же формат изображения или если возникает конфликт шаблонов, в котором два кодека используют один и тот же шаблон идентификации, этот метод позволяет выбрать кодек, который лучше всего подходит для обработки любого конкретного изображения.

При вызове этого метода компонент обработки образов Windows (WIC) передает вам фактический поток, содержащий образ. Необходимо проверить, можно ли декодировать каждый кадр в изображении и выполнять перечисление через блоки метаданных, чтобы точно объявить возможности этого декодера в отношении конкретного передаваемого ему потока файлов. Это важно для всех декодеров, но особенно важно для форматов изображений, основанных на контейнерах TIFF. Процесс обнаружения выполняется путем сопоставления шаблонов, связанных с декодировщиками в реестре, с шаблонами в фактическом файле образа. Объявление шаблона идентификации в реестре гарантирует, что декодер всегда будет обнаружен для изображений в формате изображения. Однако декодер по-прежнему может быть обнаружен для изображений в других форматах. Например, все контейнеры TIFF включают шаблон TIFF, который является допустимым шаблоном идентификации для формата изображения TIFF. Это означает, что во время обнаружения в файлах изображений для любого формата изображения, основанного на контейнере в стиле TIFF, будут найдены по крайней мере два идентифицирующих шаблона. Один из них будет шаблоном TIFF, а другой — фактическим шаблоном формата изображения. Хотя и менее вероятно, могут возникнуть конфликты шаблонов между другими несвязанными форматами изображений. Именно поэтому открытие и арбитраж являются двухэтапным процессом. Всегда проверяйте, что поток изображений, передаваемый в QueryCapability , на самом деле является допустимым экземпляром собственного формата изображения. Кроме того, если кодек декодирует формат изображения, для которого вы не владеете спецификацией, реализация QueryCapability должна проверка наличие любой функции, которая может быть допустима в спецификации формата изображения, которую не реализует кодек. Это гарантирует, что пользователи не будут испытывать ненужные сбои декодирования или получать непредвиденные результаты с помощью кодека.

Перед выполнением любой операции с изображением необходимо сохранить текущую позицию потока, чтобы можно было восстановить его в исходное положение перед возвратом из метода . Перечисление WICBitmapDecoderCapabilities , указывающее возможности, определяется следующим образом:

enum WICBitmapDecoderCapabilities
{   
   WICBitmapDecoderCapabilitySameEncoder,
   WICBitmapDecoderCapabilityCanDecodeAllImages,
   WICBitmapDecoderCapabilityCanDecodeSomeImages,
   WICBitmapDecoderCapabilityCanEnumerateMetadata,
   WICBitmapDecoderCapabilityCanDecodeThumbnail
}

Объявлять WICBitmapDecoderCapabilitySameEncoder следует только в том случае, если кодировщик закодировал изображение. Проверив, можно ли декодировать каждый кадр в контейнере, объявите либо WICBitmapDecoderCapabilityCanDecodeSomeImages , если можно декодировать некоторые, но не все кадры, WICBitmapDecoderCapabilityCanDecodeAllImages , если вы можете декодировать все кадры, либо , если вы не можете декодировать ни один из них. (Эти два перечисления являются взаимоисключающими; если вы возвращаете WICBitmapDecoderCapabilityCanDecodeAllImages, WICBitmapDecoderCapabilityCanDecodeSomeImages будут игнорироваться.) Объявите WICBitmapDecoderCapabilityCanEnumerateMetadata после проверки возможности перечисления через блоки метаданных в контейнере образа. Вам не нужно проверка эскиза в каждом кадре. Если есть глобальный эскиз и его можно декодировать, можно объявить WICBitmapDecoderCapabilityCanDecodeThumbnail. Если глобальный эскиз отсутствует, попробуйте декодировать эскиз для кадра 0. Если в любом из этих мест нет эскиза, не объявляйте эту возможность.

После определения возможностей декодера в отношении потока изображений, переданного этому методу, выполните операцию OR с wiCBitmapDecoderCapabilities , вы убедились, что этот декодер может работать с этим изображением, и возвратите результат. Перед возвратом не забудьте восстановить поток в исходное положение.

Initialize

Инициализация вызывается приложением после выбора декодера для декодирования определенного изображения. Поток изображения передается декодеру, и вызывающий объект может при необходимости указать параметр кэша WICDecodeOptions для работы с метаданными в файле.

enum WICDecodeOptions
{
   WICDecodeMetadataCacheOnDemand,
   WICDecodeMetadataCacheOnLoad
}

Некоторые приложения используют метаданные больше, чем другие. Большинству приложений не требуется доступ ко всем метаданным в файле изображения и они будут запрашивать определенные метаданные по мере необходимости. Другие приложения предпочли бы кэшировать все метаданные вперед, чем сохранять файловый поток открытым и выполнять дисковые операции ввода-вывода каждый раз, когда им потребуется доступ к метаданным. Если вызывающий объект не указывает параметр кэша метаданных, поведением кэширования по умолчанию должно быть кэширование по запросу. Это означает, что метаданные не должны загружаться в память до тех пор, пока приложение не запросит эти метаданные. Если приложение указывает WICDecodeMetadataCacheOnLoad, метаданные должны быть немедленно загружены в память и кэшированы. Если метаданные кэшируются при загрузке, файловый поток может быть освобожден после кэширования метаданных.

GetContainerFormat

Чтобы реализовать GetContainerFormat, просто верните GUID формата изображения, для которого создается экземпляр декодера. Этот метод также реализован в IWICMetadataBlockReader и IWICBitmapEncoder.

GetDecoderInfo

GetDecoderInfo возвращает объект IWICBitmapDecoderInfo . Чтобы получить объект IWICBitmapDecoderInfo , просто передайте GUID декодера в метод CreateComponentInfo в IWICImagingFactory, а затем запросите интерфейс IWICBitmapDecoderInfo , как показано в следующем примере.

IWICComponentInfo* pComponentInfo = NULL;
HRESULT hr;
 
hr = m_pImagingFactory->CreateComponentInfo(CLSID_This, &pComponentInfo);

hr = pComponentInfo->QueryInterface(IID_IWICBitmapDecoderInfo, (void**)ppIDecoderInfo);

GetFrameCount

GetFrameCount просто возвращает количество кадров в контейнере. Некоторые форматы контейнеров поддерживают несколько кадров, а другие — только один кадр на контейнер.

GetFrame

GetFrame является важным методом в интерфейсе IWICBitmapDecoder , так как кадр содержит фактические биты изображения, а объект декодера кадра, возвращенный этим методом, является объектом, который выполняет фактическое декодирование запрошенного изображения. Это другой объект, который необходимо реализовать при записи декодера. Дополнительные сведения о декодерах кадров см. в разделе Реализация IWICBitmapFrameDecode.

GetPreview

GetPreview возвращает предварительный просмотр изображения. Подробное описание предварительных версий см. в разделе Реализация метода IWICBitmapEncoder в интерфейсе Implementing IWICBitmapEncoder .

Если формат изображения содержит внедренный предварительный просмотр JPEG, настоятельно рекомендуется вместо написания декодера JPEG для его декодирования делегировать декодеру JPEG, который поставляется с платформой WIC для декодирования предварительных просмотров и эскизов. Для этого найдите начало данных изображения предварительного просмотра в потоке и вызовите метод CreateDecoderFromStream в IWICImagingFactory.

IWICBitmapDecoder* pPreviewDecoder = NULL;
IWICBitmapFrameDecode* pPreviewFrame = NULL;
IWICBitmapSource* pPreview = NULL;
HRESULT hr;

hr = m_pImagingFactory->CreateDecoderFromStream(
                               m_pStream, NULL, 
                               WICDecodeMetadataCacheOnDemand, &pPreviewDecoder);
hr = pPreviewDecoder->GetFrame(0, pPreviewFrame);
hr = pPreviewFrame->QueryInterface(IID_IWICBitmapSource, (void**)&pPreview);

Reference

IWICBitmapDecoder

IWICBitmapFrameDecode

Основные понятия

Интерфейсы декодера

Реализация IWICBitmapCodecProgressNotification (декодер)

Написание кодека WIC-Enabled

Общие сведения о компоненте обработки образов Windows