實作 IWICMetadataBlockReader
IWICMetadataBlockReader
多個中繼資料區塊通常存在於影像中,每個區塊都會以不同格式公開不同類型的資訊。 在 Windows 映像處理元件 (WIC) 模型中,元資料處理程式是可在執行時間探索的相異元件,例如解碼器。 每個元資料格式都有個別的處理常式,而且每個元資料處理程式都可以搭配任何支援其處理之元資料格式的影像格式使用。 因此,如果您的影像格式支援 EXIF、XMP、IPTC 或其他格式,您可以利用隨附 WIC 之這些格式的標準元資料處理程式,而您不需要自行撰寫。 當然,如果您建立新的元資料格式,您必須為其撰寫元資料處理程式,這會在執行時間探索並叫用,就像標準格式一樣。
注意
如果您的影像格式是以標記影像檔案格式為基礎, (TIFF) 或 JPEG 容器,除非您開發新的或專屬元資料格式,否則您不需要撰寫任何元資料處理程式) (。 在 TIFF 和 JPEG 容器中,中繼資料區塊位於 IFD 內,而且每個容器都有不同的 IFD 結構。 WIC 會針對這兩種容器格式提供 IFD 處理常式,這些格式會巡覽 IFD 結構,並委派給標準元資料處理程式,以存取它們內的中繼資料。 因此,如果您的影像格式是以其中一個容器為基礎,您可以自動利用 WIC IFD 處理常式。 不過,如果您有專屬的容器格式具有自己的唯一最上層元資料結構,您必須撰寫處理常式,以巡覽該最上層結構並委派至適當的元資料處理程式,就像 IFD 處理常式 do.)
WIC 為應用程式提供一層抽象概念,讓應用程式能夠透過一組一致的介面,以相同的方式處理所有影像格式,WIC 為編解碼器作者提供元資料格式的抽象層。 如先前所述,編解碼器作者通常不需要直接使用影像中可能存在的各種元資料格式。 不過,每個編解碼器作者都會負責提供列舉中繼資料區塊的方法,以便探索並具現化每個區塊的適當元資料處理程式。
您必須在框架層級解碼類別上實作此介面。 如果您的影像格式會在任何個別影像畫面格之外公開全域中繼資料,您可能也需要在容器層級解碼器類別上實作它。
interface IWICMetadataBlockReader : IUnknown
{
// All methods required
HRESULT GetContainerFormat ( GUID *pguidContainerFormat );
HRESULT GetCount ( UINT *pcCount );
HRESULT GetEnumerator ( IEnumUnknown **ppIEnumMetadata );
HRESULT GetReaderByIndex ( UINT nIndex, IWICMetadataReader **ppIMetadataReader );
}
GetContainerFormat
GetContainerFormat與實作 IWICBitmapDecoder上的GetContainerFormat方法相同。
GetCount
GetCount 會傳回與框架相關聯的最上層中繼資料區塊數目。
GetEnumerator
GetEnumerator 會傳回列舉值,呼叫端可用來列舉框架中的中繼資料區塊,並讀取其中繼資料。 若要實作這個方法,您必須為每個中繼資料區塊建立中繼資料讀取器,並實作列舉物件來列舉中繼資料讀取器集合。 列舉物件必須實作 IEnumUnknown ,因此當您在 ppIEnumMetadata 參數中傳回它時,可以將它轉換成 IEnumUnknown。
實作列舉物件時,您可以在第一次建立 IWICMetadataBlockReader 物件或第一次建立列舉物件時建立所有中繼資料讀取器,也可以在 IEnumUnknown::Next 方法的實作內建立它們。 在許多情況下,建立它們更有效率,但在下列範例中,區塊讀取器全都是在建構函式中建立,以節省空間。
public class MetadataReaderEnumerator : public IEnumUnknown
{
UINT m_current;
UINT m_blockCount;
IWICMetadataReader** m_ppMetadataReader;
IStream* m_pStream;
MetadataReaderEnumerator()
{
// Set m_blockCount to the number of metadata blocks in the frame.
...
m_ppMetadataReader = IWICMetadataReader*[m_blockCount];
m_current = 0;
for (UINT x=0; x < m_blockCount; x++)
{
// Find the position in the file where the xth
// block of metadata lives and seek m_piStream
// to that position.
...
m_pComponentFactory->CreateMetadataReaderFromContainer(
GUID_ContainerFormatTiff,
NULL,
WICPersistOptions.WICPersistOptionsDefault |
WICMetadataCreationOptions.WICMetadataCreationDefault,
m_pStream, &m_ppMetadataReader[x]);
}
}
// Implementation of IEnumUnknown and IUnknown interfaces
...
}
若要建立中繼資料讀取器,請使用 CreateMetadataReaderFromContainer 方法。 叫用此方法時,您會在 guidContainerFormat 參數中傳入容器格式的 GUID。 如果您有中繼資料讀取器的廠商喜好設定,您可以在 pGuidVendor 參數中傳遞慣用廠商的 GUID。 例如,如果您的公司撰寫元資料處理程式,而且您想要在存在時使用自己的處理常式,則可以傳入廠商 GUID。 在大部分情況下,您只會傳遞 Null,並讓系統選取適當的中繼資料讀取器。 如果您要求特定廠商,且該廠商在電腦上已安裝中繼資料讀取器,WIC 會傳回該廠商的讀取器。 不過,如果要求的廠商未在電腦上安裝中繼資料讀取器,而且如果有可用的適當中繼資料讀取器,即使該讀取器不是來自慣用的廠商,也會傳回該讀取器。 如果區塊中的元資料類型電腦上沒有中繼資料讀取器,元件處理站會傳回未知元資料處理程式,這會將中繼資料區塊視為二進位大型物件 (BLOB) ,而且不會嘗試剖析檔案中的中繼資料區塊。
針對 dwOptions 參數,請在適當的 WICPersistOptions 與適當的 WICMetadataCreationOptions之間執行 OR 作業。 WICPersistOptions描述容器的配置方式。小端是預設值。
enum WICPersistOptions
{
WICPersistOptionDefault,
WICPersistOptionLittleEndian,
WICPersistOptionBigEndian,
WICPersistOptionStrictFormat,
WICPersistOptionNoCacheStream,
WICPersistOptionPreferUTF8
};
WICMetadataCreationOptions指定您是否要在電腦上找到任何可讀取特定區塊元資料格式的中繼資料讀取器,取得 UnknownMetadataHandler。 WICMetadataCreationAllowUnknown 是預設值,您應該一律允許建立 UnknownMetadtataHandler。 UnknownMetadataHandler 會將無法辨識的中繼資料視為 BLOB。 它無法剖析它,但會將它寫出至資料流程做為 BLOB,並在編碼期間將其寫回資料流程時保持不變。 這可讓您安全地針對未隨附于系統的專屬中繼資料或元資料格式建立元資料處理程式。 因為中繼資料會保持不變,即使電腦上沒有可辨識它的處理常式,在稍後安裝適當的元資料處理程式時,中繼資料仍會存在,而且可以讀取。 如果您不允許建立 UnknownMetadataHandler,替代方式是捨棄或覆寫無法辨識的中繼資料。 這是資料遺失的形式。
注意
如果您為專屬中繼資料撰寫自己的元資料處理程式,就不應該包含中繼資料區塊本身外部任何專案的參考。 即使 UnknownMetadataHandler 會保留中繼資料不變,但檔案編輯時,中繼資料仍會移動,而且當發生此情況時,對本身區塊以外的任何專案的任何參考將不再有效。
enum WICMetadataCreationOptions
{
WICMetadataCreationDefault = 0x00000000,
WICMetadataCreationAllowUnknown = WICMetadataCreationDefault,
WICMetadataCreationFailUnknown = 0x00010000,
WICMetadataCreationMask = 0xFFFF0000
};
pIStream參數是您要解碼的實際資料流程。 在傳入資料流程之前,您應該先搜尋您要要求讀取器的中繼資料區塊開頭。 IStream中目前位置之中繼資料區塊的適當中繼資料讀取器將會在ppiReader參數中傳回。
GetReaderByIndex
GetReaderByIndex 會在集合中要求的索引傳回中繼資料讀取器。
相關主題
-
參考
-
概念