讀取和寫入影像中繼資料的概觀

本主題提供如何使用 Windows 映像元件 (WIC) API 來讀取和寫入內嵌在影像檔案中的中繼資料的概觀。

本主題包含下列各節。

必要條件

若要瞭解本主題,您應該熟悉 WIC 中繼資料系統,如 WIC 中繼資料概觀中所述。 您也應該熟悉用來讀取和寫入中繼資料的查詢語言,如 中繼資料查詢語言概觀中所述。

簡介

WIC 為應用程式開發人員提供元件物件模型 (COM) 元件,以讀取和寫入內嵌在圖像檔中的中繼資料。 有兩種方式可讀取和寫入中繼資料:

  • 使用查詢讀取器/寫入器和查詢運算式,查詢區塊內巢狀區塊或特定中繼資料的中繼資料區塊。
  • 使用元資料處理程式 (中繼資料讀取器或中繼資料寫入器) 來存取巢狀中繼資料區塊或中繼資料區塊內的特定中繼資料。

其中最簡單的方式是使用查詢讀取器/寫入器和查詢運算式來存取中繼資料。 當查詢寫入器 (IWICMetadataQueryWriter) 時,會使用查詢讀取器 (IWICMetadataQueryReader) 來讀取中繼資料。 這兩者都使用查詢運算式來讀取或寫入所需的中繼資料。 在幕後,查詢讀取器 (和寫入器) 會使用元資料處理程式來存取查詢運算式所描述的中繼資料。

更進階的方法是直接存取元資料處理程式。 元資料處理程式是使用 IWICMetadataBlockReader (IWICMetadataBlockReader) 或 區塊寫入器 (IWICMetadataBlockWriter) ,從個別框架取得。 可用的元資料處理程式有兩種類型的中繼資料讀取器, (IWICMetadataReader) 和中繼資料寫入 器 (IWICMetadataWriter) 。

本主題的範例中會使用 JPEG 影像檔內容的下圖。 此圖表所代表的影像是使用 Microsoft 小畫家 所建立;評等中繼資料是使用 Windows Vista 的「相片庫」功能來新增。

具有評等中繼資料的 jpeg 影像圖例

使用查詢讀取器讀取 Metadadata

讀取中繼資料最簡單的方式是使用查詢讀取 器介面 IWICMetadataQueryReader。 查詢讀取器可讓您使用查詢運算式來讀取中繼資料區塊和中繼資料區塊內的專案。

有三種方式可取得查詢讀取器:透過點陣圖解碼器 (IWICBitmapDecoder) 、透過其個別畫面格 (IWICBitmapFrameDecode) ,或透過查詢寫入器 (IWICMetadataQueryWriter) 。

取得查詢讀取器

下列範例程式碼示範如何從影像處理站取得點陣圖解碼器,並擷取個別點陣圖框架。 此程式碼也會執行從解碼框架取得查詢讀取器所需的設定工作。

IWICImagingFactory *pFactory = NULL;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pFrameDecode = NULL;
IWICMetadataQueryReader *pQueryReader = NULL;
IWICMetadataQueryReader *pEmbedReader = NULL;
PROPVARIANT value;

// Initialize COM
CoInitialize(NULL);

// Initialize PROPVARIANT
PropVariantInit(&value);

//Create the COM imaging factory
HRESULT hr = CoCreateInstance(
    CLSID_WICImagingFactory,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IWICImagingFactory,
    (LPVOID*)&pFactory);

// Create the decoder
if (SUCCEEDED(hr))
{
    hr = pFactory->CreateDecoderFromFilename(
        L"test.jpg",
        NULL,
        GENERIC_READ,
        WICDecodeMetadataCacheOnDemand,
        &pDecoder);
}

// Get a single frame from the image
if (SUCCEEDED(hr))
{
    hr = pDecoder->GetFrame(
         0,  //JPEG has only one frame.
         &pFrameDecode); 
}

使用映射處理站的 CreateDecoderFromFilename 方法來取得test.jpg檔案的點陣圖解碼器。 在此方法中,第四個參數會設定為 WICDecodeMetadataCacheOnDemand 從 WICDecodeOptions 列舉的值。 這會告訴解碼器在需要中繼資料時快取中繼資料;藉由取得查詢讀取器或基礎中繼資料讀取器。 使用此選項可讓您將資料流程保留在快速中繼資料編碼所需的中繼資料,並啟用 JPEG 影像的無遺失解碼。 或者,您可以使用另一個 WICDecodeOptions 值 WICDecodeMetadataCacheOnLoad,在載入影像後立即快取內嵌影像中繼資料。

若要取得框架的查詢讀取器,請簡單呼叫框架的 GetMetadataQueryReader 方法。 下列程式碼示範此呼叫。

// Get the query reader
if (SUCCEEDED(hr))
{
    hr = pFrameDecode->GetMetadataQueryReader(&pQueryReader);
}

同樣地,查詢讀取器也可以在解碼器層級取得。 對解碼器 GetMetadataQueryReader 方法的簡單呼叫會取得解碼器的查詢讀取器。 解碼器的查詢讀取器與框架的查詢讀取器不同,會讀取個別畫面外之影像的中繼資料。 不過,此案例並不常見,原生映射格式不支援此功能。 WIC 所提供的原生影像 CODECS 會讀取和寫入框架層級的中繼資料,即使是 JPEG 之類的單一畫面格式也一樣。

讀取中繼資料

在您繼續實際讀取中繼資料之前,請先查看 JPEG 檔案的下圖,其中包含內嵌中繼資料區塊和要擷取的實際資料。 此圖表提供圖說文字給影像內的特定中繼資料區塊和專案,並提供中繼資料查詢運算式給每個區塊或專案。

具有中繼資料圖說文字的 jpeg 影像圖例

若要依名稱查詢內嵌中繼資料區塊或特定專案,請呼叫 GetMetadataByName 方法。 這個方法會採用查詢運算式和 PROPVARIANT ,其中會傳回中繼資料專案。 下列程式碼會查詢巢狀中繼資料區塊,並在找到時,將 PROPVARIANT 值所提供的 IUnknown 元件轉換為查詢讀取器。

if (SUCCEEDED(hr))
{
    // Get the nested IFD reader
    hr = pQueryReader->GetMetadataByName(L"/app1/ifd", &value);
    if (value.vt == VT_UNKNOWN)
    {
        hr = value.punkVal->QueryInterface(IID_IWICMetadataQueryReader, (void **)&pEmbedReader);
    }
    PropVariantClear(&value); // Clear value for new query
}

查詢運算式 「/app1/ifd」 正在查詢 App1 區塊中巢狀的 IFD 區塊。 JPEG 影像檔包含 IFD 巢狀中繼資料區塊,因此 PROPVARIANT 會以變數類型傳回, (vt VT_UNKNOWN) 和 IUnknown 介面的指標 (punkVal) 。 然後,您可以查詢查詢讀取器的 IUnknown 介面。

下列程式碼會根據相對於巢狀 IFD 區塊的新查詢讀取器來示範新的查詢。

if (SUCCEEDED(hr))
{
    hr = pEmbedReader->GetMetadataByName(L"/{ushort=18249}", &value);
    PropVariantClear(&value); // Clear value for new query
}

查詢運算式 「/{ushort=18249}」 會查詢標籤 18249 底下內嵌 MicrosoftPhoto 評等的 IFD 區塊。 PROPVARIANT值現在會包含 的 VT_UI2 實值型別和資料值 50。

不過,在查詢特定資料值之前,不需要取得巢狀區塊。 例如,您可以改用根中繼資料區塊和下列程式碼中顯示的查詢來取得相同的資訊,而不是查詢巢狀 IFD,然後查詢 MicrosoftPhoto 評等。

if (SUCCEEDED(hr))
{
    hr = pQueryReader->GetMetadataByName(L"/app1/ifd/{ushort=18249}", &value);
    PropVariantClear(&value);
}

除了查詢中繼資料區塊中的特定中繼資料專案之外,您也可以列舉中繼資料區塊中的所有中繼資料專案, (不包含巢狀中繼資料區塊中的中繼資料專案) 。 若要列舉目前區塊中的中繼資料專案,會使用查詢讀取器的 GetEnumeration 方法。 這個方法會取得填入目前 區塊中中繼資料專案的 IEnumString 介面。 例如,下列程式碼會列舉稍早取得之巢狀 IFD 區塊的 XMP 評等和 MicrosoftPhoto 評等。

IEnumString *metadataItems = NULL;

if (SUCCEEDED(hr))
{
    hr = pEmbedReader->GetEnumerator(&metadataItems);
}

如需識別各種影像格式和元資料格式適當標籤的詳細資訊,請參閱 原生影像格式中繼資料查詢

其他查詢讀取器方法

除了讀取中繼資料之外,您也可以取得查詢讀取器的其他資訊,並透過其他方式取得中繼資料。 查詢讀取器提供兩種方法,提供查詢讀取器的相關資訊 :GetContainerFormatGetLocation

使用內嵌查詢讀取器,您可以使用 GetContainerFormat 來判斷中繼資料區塊的類型,而且您可以呼叫 GetLocation 來取得相對於根中繼資料區塊的路徑。 下列程式碼會查詢內嵌查詢讀取器的位置。

// Determine the metadata block format

if (SUCCEEDED(hr))
{
    hr = pEmbedReader->GetContainerFormat(&containerGUID);
}

// Determine the query reader's location
if (SUCCEEDED(hr))
{
    UINT length;
    WCHAR readerNamespace[100];
    hr = pEmbedReader->GetLocation(100, readerNamespace, &length);
}

對內嵌查詢讀取器的 GetContainerFormat 呼叫會傳回 IFD 元資料格式 GUID。 呼叫 GetLocation 會傳回 「/app1/ifd」 的命名空間;為您提供將執行新查詢讀取器後續查詢的相對路徑。 當然,上述程式碼並不實用,但會示範如何使用 GetLocation 方法來尋找巢狀中繼資料區塊。

使用查詢寫入器撰寫中繼資料

注意

本節中提供的一些程式碼範例不會顯示在撰寫中繼資料所需的實際步驟內容中。 若要在工作範例的內容中檢視程式碼範例,請參閱操作說明:使用中繼資料重新編碼影像教學課程。

 

寫入中繼資料的主要元件是 IWICMetadataQueryWriter) (查詢寫入器。 查詢寫入器可讓您設定和移除中繼資料區塊內的中繼資料區塊和專案。

就像查詢讀取器一樣,有三種方式可以取得查詢寫入器:透過點陣圖編碼器 (IWICBitmapEncoder) 、透過其個別畫面格 (IWICBitmapFrameEncode) ,或透過 IWICFastMetadataEncoder) (快速中繼資料編碼器。

取得查詢寫入器

最常見的查詢寫入器是點陣圖的個別框架。 此查詢寫入器會設定和移除影像框架的中繼資料區塊和專案。 若要取得影像框架的查詢寫入器,請呼叫框架的 GetMetadataQueryWriter 方法。 下列程式碼示範取得框架查詢寫入器的簡單方法呼叫。

IWICMetadataQueryWriter &pFrameQWriter = NULL;

//Obtain a query writer from the frame.
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);

同樣地,也可以取得編碼器層級的查詢寫入器。 對編碼器 GetMetadataQueryWriter 方法的簡單呼叫會取得編碼器的查詢寫入器。 編碼器的查詢寫入器,與框架的查詢寫入器不同,會在個別畫面外寫入影像的中繼資料。 不過,此案例並不常見,原生映射格式不支援此功能。 WIC 所提供的原生影像編解碼器會讀取和寫入畫面層級的中繼資料,即使是 JPEG 之類的單一畫面格式也一樣。

您也可以直接從映射處理站取得查詢寫入器, (IWICImagingFactory) 。 傳回查詢寫入器的映射處理站方法有兩種: CreateQueryWriterCreateQueryWriterFromReader

CreateQueryWriter 會為指定的元資料格式和廠商建立查詢寫入器。 此查詢寫入器可讓您撰寫特定元資料格式的中繼資料,並將其新增至影像。 下列程式碼示範 CreateQueryWriter 呼叫,以建立 XMP 查詢寫入器。

IWICMetadataQueryWriter *pXMPWriter = NULL;

// Create XMP block
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriter(
        GUID_MetadataFormatXMP,
        &vendor,
        &pXMPWriter);

在此範例中,易記名稱 GUID_MetadataFormatXMP 會當做 guidMetadataFormat 參數使用。 它代表 XMP 元資料格式 GUID,而廠商則代表 Microsoft 建立的處理常式。 或者,如果沒有任何其他 XMP 處理常式存在,則可以將 Null 當做具有相同結果的 pguidVendor 參數傳遞。 如果自訂 XMP 處理常式與原生 XMP 處理常式一起安裝,則為廠商傳遞 Null 會導致傳回最低 GUID 的查詢寫入器。

CreateQueryWriterFromReader 類似于 CreateQueryWriter 方法,不同之處在于它會使用查詢讀取器所提供的資料預先填入新的查詢寫入器。 這適用于在維護現有中繼資料時重新編碼影像,或移除不必要的中繼資料。 下列程式碼示範 CreateQueryWriterFromReader 呼叫。

hr = pFrameDecode->GetMetadataQueryReader(&pFrameQReader);

// Copy metadata using query readers
if(SUCCEEDED(hr) && pFrameQReader)
{
    IWICMetadataQueryWriter *pNewWriter = NULL;

    GUID vendor = GUID_VendorMicrosoft;
    hr = pFactory->CreateQueryWriterFromReader(
        pFrameQReader,
        &vendor,
        &pNewWriter);

新增中繼資料

取得查詢寫入器之後,您可以使用它來新增中繼資料區塊和專案。 若要寫入中繼資料,您可以使用查詢寫入器的 SetMetadataByName 方法。 SetMetadataByName 採用兩個參數:查詢運算式 (wzName) ,以及 PROPVARIANT (pvarValue) 的指標。 查詢運算式會定義要設定的區塊或專案,而 PROPVARIANT 會提供要設定的實際資料值。

下列範例示範如何使用先前使用 CreateQueryWriter 方法取得的 XMP 查詢寫入器來新增標題。

// Write metadata to the XMP writer
if (SUCCEEDED(hr))
{
    PROPVARIANT value;
    PropVariantInit(&value);

    value.vt = VT_LPWSTR;
    value.pwszVal = L"Metadata Test Image.";
   
    hr = pXMPWriter->SetMetadataByName(L"/dc:title", &value);

    PropVariantClear(&value);
}

在此範例中,值的類型 (vt) 設定為 VT_LPWSTR ,表示字串會當做資料值使用。 因為 值的型別是字串, 所以 pwszVal 是用來設定要使用的標題。 接著會使用查詢運算式 「/dc:title」 和新設定的 PROPVARIANT來呼叫SetMetadataByName。 使用的查詢運算式表示應該設定數位相機中的 title 屬性, (dc) 架構。 請注意,運算式不是 「/xmp/dc:title」;這是因為查詢寫入器已經專屬於 XMP,而且不包含內嵌的 XMP 區塊,「/xmp/dc:title」 會建議。

此時,您實際上尚未將任何中繼資料新增至影像框架。 您只要填入資料寫入器即可。 若要將查詢寫入器所代表的中繼資料區塊加入框架中,您再次使用查詢寫入器做為PROPVARIANT的值呼叫SetMetadataByName。 這會有效地將查詢寫入器中的中繼資料複製到影像框架。 下列程式碼示範如何將先前取得的 XMP 查詢寫入器中的中繼資料新增至框架的根中繼資料區塊。

// Get the frame's query writer and write the XMP query writer to it
if (SUCCEEDED(hr))
{
    hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);

    // Copy the metadata in the XMP query writer to the frame
    if (SUCCEEDED(hr))
    {
        PROPVARIANT value;

        PropVariantInit(&value);
        value.vt = VT_UNKNOWN;
        value.punkVal = pXMPWriter;
        value.punkVal->AddRef();

        hr = pFrameQWriter->SetMetadataByName(L"/", &value);

        PropVariantClear(&value);
    }
}

在此範例中,會使用 (vt) 的值 VT_UNKOWN 類型;表示 COM 介面實數值型別。 接著會使用 XMP 查詢寫入器 (piXMPWriter) 做為 PROPVARIANT的值,並使用 AddRef 方法新增其參考。 最後,XMP 查詢寫入器是藉由呼叫框架的 SetMetadataByName 方法,並傳遞查詢運算式 「/」,指出根區塊,以及新設定的 PROPVARIANT 來設定。

注意

如果框架已經包含您嘗試新增的中繼資料區塊,則會新增您要新增的中繼資料,並覆寫現有的中繼資料。

 

移除中繼資料

查詢寫入器也可讓您藉由呼叫 RemoveMetadataByName 方法來移除中繼資料。 RemoveMetadataByName 會採用查詢運算式,並在中繼資料區塊或專案存在時移除。 下列程式碼示範如何移除先前新增的標題。

if (SUCCEEDED(hr))
{
    hr = pFrameQWriter->RemoveMetadataByName(L"/xmp/dc:title");
}

下列程式碼示範如何移除整個 XMP 中繼資料區塊。

if (SUCCEEDED(hr))
{
    hr = pFrameQWriter->RemoveMetadataByName(L"/xmp");
}

複製重新編碼的中繼資料

注意

只有在來源和目的地影像格式相同時,本節中的程式碼才有效。 當編碼為不同的影像格式時,您無法在單一作業中複製所有影像的中繼資料。

 

若要在將影像重新編碼為相同的影像格式時保留中繼資料,有一種方法可用來複製單一作業中的所有中繼資料。 每個作業都會遵循類似的模式;每個都會將解碼框架的中繼資料直接設定為要編碼的新畫面。

複製中繼資料的慣用方法是使用解碼框架的區塊讀取器,初始化新框架的區塊寫入器。 下列程式碼示範這個方法。

if (SUCCEEDED(hr) && formatsEqual)
{
    // Copy metadata using metadata block reader/writer
    if (SUCCEEDED(hr))
    {
        pFrameDecode->QueryInterface(
            IID_IWICMetadataBlockReader,
            (void**)&pBlockReader);
    }
    if (SUCCEEDED(hr))
    {
        pFrameEncode->QueryInterface(
            IID_IWICMetadataBlockWriter,
            (void**)&pBlockWriter);
    }
    if (SUCCEEDED(hr))
    {
        pBlockWriter->InitializeFromBlockReader(pBlockReader);
    }
}

在此範例中,會分別從來源畫面格和目的地框架取得區塊讀取器和區塊寫入器。 然後,區塊寫入器會從區塊讀取器初始化。 這會使用預先填入區塊讀取器的中繼資料,初始化區塊讀取器。

複製中繼資料的另一種方法是使用編碼器的查詢寫入器來寫入查詢讀取器所參考的中繼資料區塊。 下列程式碼示範這個方法。

if (SUCCEEDED(hr) && formatsEqual)
{
    hr = pFrameDecode->GetMetadataQueryReader(&pFrameQReader);

    // Copy metadata using query readers
    if(SUCCEEDED(hr))
    {
        hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
        if (SUCCEEDED(hr))
        {
            PropVariantClear(&value);
            value.vt=VT_UNKNOWN;
            value.punkVal=pFrameQReader;
            value.punkVal->AddRef();
            hr = pFrameQWriter->SetMetadataByName(L"/", &value);
            PropVariantClear(&value);
        }
    }
}

在這裡,會從解碼的框架取得查詢讀取器,然後使用做為 PROPVARIANT 的屬性值,並將實值型別設定為 VT_UNKNOWN。 取得編碼器的查詢寫入器,並使用查詢運算式 「/」 在根導覽路徑設定中繼資料。 您也可以藉由將查詢運算式調整為所需的位置,在設定巢狀中繼資料區塊時使用此方法。

同樣地,您可以使用映射處理站的 CreateQueryWriterFromReader 方法,根據解碼框架的查詢讀取器來建立查詢寫入器。 在此作業中建立的查詢寫入器會預先填入來自查詢讀取器的中繼資料,然後可以在框架中設定。 下列程式碼示範 CreateQueryWriterFromReader 複製作業。

IWICMetadataQueryWriter *pNewWriter = NULL;

GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriterFromReader(
    pFrameQReader,
    &vendor,
    &pNewWriter);

if (SUCCEEDED(hr))
{
    // Get the frame's query writer
    hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
}

// Set the query writer to the frame.
if (SUCCEEDED(hr))
{
    PROPVARIANT value;

    PropVariantInit(&value);
    value.vt = VT_UNKNOWN;
    value.punkVal = pNewWriter;
    value.punkVal->AddRef();
    hr = pFrameQWriter->SetMetadataByName(L"/",&value);
}

這個方法會使用個別的查詢寫入器來建立,該寫入器是以查詢讀取器的資料為基礎。 這個新的查詢寫入器接著會在框架中設定。

同樣地,只有在來源和目的地影像具有相同格式時,才能複製中繼資料的這些作業。 這是因為不同的影像格式會將中繼資料區塊儲存在不同的位置。 例如,JPEG 和 TIFF 都支援 XMP 中繼資料區塊。 在 JPEG 映射中,XMP 區塊位於根中繼資料區塊,如 WIC 中繼資料概觀中所述。 不過,在 TIFF 映射中,XMP 區塊會巢狀于根 IFD 區塊中。 下圖說明 JPEG 影像與具有相同評等中繼資料的 TIFF 影像之間的差異。

jpeg 和 tiff 比較。

快速中繼資料編碼

不一定需要重新編碼影像,以將新的中繼資料寫入其中。 您也可以使用快速中繼資料編碼器來撰寫中繼資料。 快速中繼資料編碼器可以將有限的中繼資料寫入影像,而不需重新編碼影像。 這可藉由在部分元資料格式所提供的空白填補內寫入新的中繼資料來完成。 支援中繼資料填補的原生元資料格式為 Exif、IFD、GPS 和 XMP。

將填補新增至中繼資料區塊

您必須先在中繼資料區塊內有空間才能執行快速中繼資料編碼,才能寫入更多中繼資料。 如果現有填補內沒有足夠的空間可寫入新的中繼資料,則快速的中繼資料編碼將會失敗。 若要將中繼資料填補新增至影像,必須重新編碼影像。 如果填補的中繼資料區塊支援,您可以使用查詢運算式,以新增任何其他中繼資料專案的方式新增填補。 下列範例示範如何將填補新增至內嵌在 App1 區塊中的 IFD 區塊。

if (SUCCEEDED(hr))
{
    // Add metadata padding
    PROPVARIANT padding;

    PropVariantInit(&padding);
    padding.vt = VT_UI4;
    padding.uiVal = 4096; // 4KB

    hr = pFrameQWriter->SetMetadataByName(L"/app1/ifd/PaddingSchema:padding", &padding);

    PropVariantClear(&padding);
}

若要新增填補,請建立類型為 VT_UI4 的 PROPVARIANT,以及對應至要加入之填補位元組數目的值。 一般值為 4096 個位元組。 此資料表中有 JPEG、TIFF 和 JPEG-XR 的中繼資料查詢。

中繼資料格式 JPEG 中繼資料查詢 TIFF、JPEG-XR 中繼資料查詢
IFD /app1/ifd/PaddingSchema:Padding /ifd/PaddingSchema:Padding
Exif /app1/ifd/exif/PaddingSchema:Padding /ifd/exif/PaddingSchema:Padding
XMP /xmp/PaddingSchema:Padding /ifd/xmp/PaddingSchema:Padding
GPS /app1/ifd/gps/PaddingSchema:Padding /ifd/gps/PaddingSchema:Padding

 

取得快速中繼資料編碼器

當您有具有中繼資料填補的影像時,可以使用映射處理站方法 CreateFastMetadataEncoderFromDecoderCreateFastMetadataEncoderFromFrameDecode來取得快速中繼資料編碼器。

如名稱所示, CreateFastMetadataEncoderFromDecoder 會建立用於解碼器層級中繼資料的快速中繼資料編碼器。 WIC 所提供的原生影像格式不支援解碼器層級中繼資料,但會在未來開發這類影像格式時提供此方法。

較常見的案例是使用 CreateFastMetadataEncoderFromFrameDecode從影像框架取得快速中繼資料編碼器。 下列程式碼會取得解碼框架的快速中繼資料編碼器,並變更 App1 區塊中的評等值。

if (SUCCEEDED(hr))
{
    IWICFastMetadataEncoder *pFME = NULL;
    IWICMetadataQueryWriter *pFMEQW = NULL;

    hr = pFactory->CreateFastMetadataEncoderFromFrameDecode(
        pFrameDecode, 
        &pFME);
}

使用快速中繼資料編碼器

您可以從快速中繼資料編碼器取得查詢寫入器。 這可讓您使用先前示範的查詢運算式來撰寫中繼資料。 在查詢寫入器中設定中繼資料之後,請認可快速中繼資料編碼器以完成中繼資料更新。 下列程式碼示範如何設定及認可中繼資料變更

    if (SUCCEEDED(hr))
    {
        hr = pFME->GetMetadataQueryWriter(&pFMEQW);
    }

    if (SUCCEEDED(hr))
    {
        // Add additional metadata
        PROPVARIANT value;

        PropVariantInit(&value);

        value.vt = VT_UI4;
        value.uiVal = 99;
        hr = pFMEQW->SetMetadataByName(L"/app1/ifd/{ushort=18249}", &value);

        PropVariantClear(&value);
    }

    if (SUCCEEDED(hr))
    {
        hr = pFME->Commit();
    }
}

如果 認可 因任何原因而失敗,您必須重新編碼影像,以確保將新的中繼資料新增至映射。

概念

Windows 映像處理元件概觀

WIC 中繼資料概觀

中繼資料查詢語言概觀

中繼資料擴充性概觀

作法:使用中繼資料重新編碼 JPEG 影像