實作 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 是用於編解碼器仲裁的方法。 (請參閱Windows 映像處理元件運作方式主題中的探索和仲裁) 。 如果兩個編解碼器能夠解碼相同的影像格式,或發生模式衝突,其中兩個編解碼器使用相同的識別模式,這個方法可讓您選取最能處理任何特定影像的編解碼器。

叫用此方法時,Windows 影像處理元件 (WIC) 會傳遞包含影像的實際資料流程。 您必須確認是否可以解碼影像中的每個框架,並透過中繼資料區塊列舉,以精確地宣告此解碼器對於傳遞給它的特定檔案資料流程所具備的功能。 這對於所有解碼器很重要,但對於以標記影像檔案格式為基礎的影像格式 (TIFF) 容器而言特別重要。 探索程式的運作方式是比對登錄中與解碼器相關聯的模式與實際映射檔中的模式。 在登錄中宣告您的識別模式,可確保您的解碼器一律會偵測到影像格式的影像。 不過,您仍然可以偵測到解碼器是否有其他格式的影像。 例如,所有 TIFF 容器都包含 TIFF 模式,這是 TIFF 影像格式的有效識別模式。 這表示,在探索期間,在影像檔中,至少有兩種識別模式可在以 TIFF 樣式容器為基礎的任何影像格式中找到。 其中一個是 TIFF 模式,另一個則會是實際的影像格式模式。 雖然不太可能,但也可能在其他不相關的影像格式之間發生模式衝突。 這就是為什麼探索和仲裁是兩階段程式的原因。 請一律確認傳遞至 QueryCapability 的影像資料流程實際上是您自己的影像格式的有效實例。 此外,如果您的編解碼器解碼您不擁有規格的影像格式, 您的 QueryCapability 實作應該檢查您的編解碼器未實作的影像格式規格下是否有任何可能有效的功能。 這可確保使用者不會遇到不必要的解碼失敗,或使用編解碼器取得非預期的結果。

在映射上執行任何作業之前,您必須先儲存資料流程的目前位置,以便先將它還原到原始位置,再從 方法傳回。 指定功能的 WICBitmapDecoderCapabilities列舉定義如下:

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

只有當編碼器是編碼影像的編碼器時,才應該宣告 WICBitmapDecoderCapabilitySameEncoder 。 確認您是否可以解碼容器中的每個框架之後,如果您可以解碼部分但並非所有畫面格,則宣告 WICBitmapDecodeDecodeCanDecodeCanDecodeCanDecodeAllImages ,如果無法解碼其中任何畫面格,則宣告 WICBitmapDecodeDecodeCanDecodeCanDeages ,或無法解碼其中任何畫面格。 (這兩個列舉互斥;如果您傳回 WICBitmapDecoderCapabilityCanDecodeAllImages則會忽略 WICBitmapDecodeDecodeRCapabilityCanDecodeSomeImages 。) 宣告 WICBitmapDecoderCapabilityCanEnumerateMetadata ,確認您可以透過映射容器中的中繼資料區塊列舉。 您不需要檢查每個畫面中的縮圖。 如果有全域縮圖,您可以解碼它,您可以宣告 WICBitmapDecoderCapabilityCanDecodeThumbnail。 如果沒有全域縮圖,則嘗試解碼 Frame 0 的縮圖。 如果上述任一位置中沒有任何縮圖,請勿宣告這項功能。

在判斷解碼器與傳遞至此方法之影像資料流程相關的功能之後,請使用您已確認此解碼器可在此影像上執行的 WICBitmapDecoderCapabilities 執行 OR 作業,並傳回結果。 在傳回之前,請記得將資料流程還原至其原始位置。

Initialize

選取解碼器來解碼特定影像之後,應用程式會叫用 Initialize。 影像資料流程會傳遞至解碼器,而呼叫端可以選擇性地指定 WICDecodeOptions 快取選項來處理檔案中的中繼資料。

enum WICDecodeOptions
{
   WICDecodeMetadataCacheOnDemand,
   WICDecodeMetadataCacheOnLoad
}

有些應用程式使用中繼資料比其他應用程式更多。 大部分的應用程式不需要存取影像檔中的所有中繼資料,而且會視需要要求特定中繼資料。 其他應用程式會預先快取所有中繼資料,而不是每次需要存取中繼資料時讓檔案資料流程保持開啟並執行磁片 I/O。 如果呼叫端未指定中繼資料快取選項,預設快取行為應該視需要快取。 這表示在應用程式發出該中繼資料的特定要求之前,不應該將中繼資料載入記憶體中。 如果應用程式指定 WICDecodeMetadataCacheOnLoad,則應該立即在記憶體中載入中繼資料並快取。 當中繼資料在載入時快取時,檔案資料流程可能會在快取中繼資料之後釋出。

GetContainerFormat

若要實作 GetContainerFormat,只要傳回具現化解碼器之影像影像格式的 GUID。 此方法也會在 IWICMetadataBlockReaderIWICBitmapEncoder上實作。

GetDecoderInfo

GetDecoderInfo 會傳回 IWICBitmapDecoderInfo 物件。 若要取得IWICBitmapDecoderInfo物件,只要將解碼器的 GUID 傳遞至IWICImagingFactory上的CreateComponentInfo方法,然後要求它的IWICBitmapDecoderInfo介面,如下列範例所示。

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

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

GetFrameCount

GetFrameCount 只會傳回容器中的畫面數。 有些容器格式支援多個框架,而其他則只支援每個容器一個框架。

GetFrame

GetFrameIWICBitmapDecoder 介面上的重要方法,因為框架包含實際的影像位,而從此方法傳回的畫面解碼器物件是執行所要求影像實際解碼的物件。 這是撰寫解碼器時需要實作的其他物件。 如需畫面解碼器的詳細資訊,請參閱 實作 IWICBitmapFrameDecode

GetPreview

GetPreview 會傳回影像的預覽。 如需預覽的詳細討論,請參閱實作 IWICBitmapEncoder 介面上的實作 IWICBitmapEncoder方法。

如果您的影像格式包含內嵌的 JPEG 預覽,強烈建議您不要撰寫 JPEG 解碼器來解碼,而是委派給 WIC 平臺隨附的 JPEG 解碼器,以進行解碼預覽和縮圖。 若要這樣做,請在資料流程中搜尋預覽影像資料的開頭,並在IWICImagingFactory上叫用CreateDecoderFromStream方法。

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);

參考

IWICBitmapDecoder

IWICBitmapFrameDecode

概念

解碼器介面

實作 IWICBitmapCodecProgressNotification (解碼器)

如何撰寫WIC-Enabled CODEC

Windows 映像處理元件概觀