이미지 메타데이터 읽기 및 쓰기 개요
이 항목에서는 WIC(Windows 이미징 구성 요소) API를 사용하여 이미지 파일에 포함된 메타데이터를 읽고 쓰는 방법에 대한 개요를 제공합니다.
이 항목에는 다음과 같은 섹션이 포함되어 있습니다.
사전 요구 사항
이 항목을 이해하려면 WIC 메타데이터 개요에 설명된 대로 WIC 메타데이터 시스템에 대해 잘 알고 있어야 합니다. 메타데이터 쿼리 언어 개요에 설명된 대로 메타데이터를 읽고 쓰는 데 사용되는 쿼리 언어에 대해서도 잘 알고 있어야 합니다.
소개
WIC는 애플리케이션 개발자에게 이미지 파일에 포함된 메타데이터를 읽고 쓸 수 있는 COM(구성 요소 개체 모델) 구성 요소를 제공합니다. 메타데이터를 읽고 쓰는 방법에는 두 가지가 있습니다.
- 쿼리 판독기/기록기 및 쿼리 식을 사용하여 중첩된 블록 또는 블록 내의 특정 메타데이터에 대한 메타데이터 블록을 쿼리합니다.
- 메타데이터 처리기(메타데이터 판독기 또는 메타데이터 기록기)를 사용하여 중첩된 메타데이터 블록 또는 메타데이터 블록 내의 특정 메타데이터에 액세스합니다.
이 중 가장 쉬운 방법은 쿼리 판독기/기록기 및 쿼리 식을 사용하여 메타데이터에 액세스하는 것입니다. 쿼리 판독기(IWICMetadataQueryReader)는 메타데이터를 읽는 데 사용되고 쿼리 작성기(IWICMetadataQueryWriter)는 메타데이터를 작성하는 데 사용됩니다. 둘 다 쿼리 식을 사용하여 원하는 메타데이터를 읽거나 씁니다. 백그라운드에서 쿼리 판독기(및 작성기)는 메타데이터 처리기를 사용하여 쿼리 식에 설명된 메타데이터에 액세스합니다.
고급 방법은 메타데이터 처리기에 직접 액세스하는 것입니다. 메타데이터 처리기는 블록 판독기(IWICMetadataBlockReader) 또는 블록 작성기(IWICMetadataBlockWriter)를 사용하여 개별 프레임에서 가져옵니다. 사용할 수 있는 두 가지 유형의 메타데이터 처리기는 메타데이터 판독기(IWICMetadataReader)와 메타데이터 기록기(IWICMetadataWriter)입니다.
JPEG 이미지 파일의 내용에 대한 다음 다이어그램은 이 항목의 예제 전체에서 사용됩니다. 이 다이어그램으로 표시되는 이미지는 Microsoft 그림판 사용하여 만들어졌으며, 등급 메타데이터는 Windows Vista의 사진 갤러리 기능을 사용하여 추가되었습니다.
쿼리 읽기 프로그램을 사용하여 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);
}
test.jpg 파일의 비트맵 디코더는 이미징 팩터리의 CreateDecoderFromFilename 메서드를 사용하여 가져옵니다. 이 메서드에서 네 번째 매개 변수는 WICDecodeOptions 열거형에서 WICDecodeMetadataCacheOnDemand 값으로 설정됩니다. 그러면 메타데이터가 필요할 때 메타데이터를 캐시하도록 디코더에 지시합니다. 쿼리 판독기 또는 기본 메타데이터 판독기를 가져옵니다. 이 옵션을 사용하면 빠른 메타데이터 인코딩에 필요한 메타데이터로 스트림을 유지할 수 있으며 JPEG 이미지의 무손실 디코딩을 사용할 수 있습니다. 또는 이미지가 로드되는 즉시 포함된 이미지 메타데이터를 캐시하는 다른 WICDecodeOptions 값인 WICDecodeMetadataCacheOnLoad를 사용할 수 있습니다.
프레임의 쿼리 판독기를 가져오려면 프레임의 GetMetadataQueryReader 메서드를 간단히 호출합니다. 다음 코드에서는 이 호출을 보여 줍니다.
// Get the query reader
if (SUCCEEDED(hr))
{
hr = pFrameDecode->GetMetadataQueryReader(&pQueryReader);
}
마찬가지로 쿼리 판독기는 디코더 수준에서 가져올 수도 있습니다. 디코더의 GetMetadataQueryReader 메서드에 대한 간단한 호출은 디코더의 쿼리 판독기를 가져옵니다. 디코더의 쿼리 판독기는 프레임의 쿼리 판독기와 달리 개별 프레임 외부에 있는 이미지에 대한 메타데이터를 읽습니다. 그러나 이 시나리오는 일반적이지 않으며 네이티브 이미지 형식은 이 기능을 지원하지 않습니다. JPEG와 같은 단일 프레임 형식에 대해서도 WIC에서 제공하는 네이티브 이미지 CODECS는 프레임 수준에서 메타데이터를 읽고 씁니다.
메타데이터 읽기
실제로 메타데이터를 읽기 전에 포함된 메타데이터 블록과 검색할 실제 데이터가 포함된 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_UNKNOWN
변수 형식(vt)과 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을 포함합니다.
그러나 특정 데이터 값을 쿼리하기 전에 중첩된 블록을 가져올 필요는 없습니다. instance 경우 중첩된 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);
}
다양한 이미지 형식 및 메타데이터 형식에 적합한 태그를 식별하는 방법에 대한 자세한 내용은 네이티브 이미지 형식 메타데이터 쿼리를 참조하세요.
추가 쿼리 판독기 메서드
메타데이터를 읽는 것 외에도 쿼리 판독기에 대한 추가 정보를 얻고 다른 방법을 통해 메타데이터를 가져올 수도 있습니다. 쿼리 판독기는 쿼리 판독기 GetContainerFormat 및 GetLocation에 대한 정보를 제공하는 두 가지 메서드를 제공합니다.
포함된 쿼리 판독기를 사용하면 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)에서 직접 쿼리 작성기를 가져올 수도 있습니다. 쿼리 작성기를 반환하는 두 가지 이미징 팩터리 메서드인 CreateQueryWriter 및 CreateQueryWriterFromReader가 있습니다.
CreateQueryWriter 는 지정된 메타데이터 형식 및 공급업체에 대한 쿼리 작성기를 만듭니다. 이 쿼리 작성기를 사용하면 특정 메타데이터 형식에 대한 메타데이터를 작성하고 이미지에 추가할 수 있습니다. 다음 코드는 XMP 쿼리 작성기를 만들기 위한 CreateQueryWriter 호출을 보여 줍니다.
IWICMetadataQueryWriter *pXMPWriter = NULL;
// Create XMP block
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriter(
GUID_MetadataFormatXMP,
&vendor,
&pXMPWriter);
이 예제에서는 식별 이름이 GUID_MetadataFormatXMP
guidMetadataFormat 매개 변수로 사용됩니다. XMP 메타데이터 형식 GUID를 나타내고 공급업체는 Microsoft에서 만든 처리기를 나타냅니다. 또는 다른 XMP 처리기가 없는 경우 동일한 결과를 가진 pguidVendor 매개 변수로 NULL을 전달할 수 있습니다. 네이티브 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은 사용할 제목을 설정하는 데 사용됩니다.
그런 다음 SetMetadataByName 은 쿼리 식 "/dc:title"과 새로 설정된 PROPVARIANT를 사용하여 호출됩니다. 사용된 쿼리 식은 디지털 카메라(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);
}
}
}
여기서는 디코딩된 프레임에서 쿼리 판독기를 가져온 다음 값 형식이 VT_UNKNOWN 설정된 PROPVARIANT 의 속성 값으로 사용됩니다. 인코더에 대한 쿼리 작성기를 가져오고 쿼리 식 "/"을 사용하여 루트 탐색 경로에서 메타데이터를 설정합니다. 쿼리 식을 원하는 위치로 조정하여 중첩된 메타데이터 블록을 설정할 때 이 메서드를 사용할 수도 있습니다.
마찬가지로 이미징 팩터리의 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);
}
이 메서드는 쿼리 판독기의 데이터를 기반으로 하는 별도의 쿼리 작성기를 사용합니다. 그러면 이 새 쿼리 작성기가 프레임에서 설정됩니다.
다시 말하지만, 메타데이터를 복사하는 이러한 작업은 원본 및 대상 이미지의 형식이 동일한 경우에만 작동합니다. 이는 이미지 형식이 서로 다른 위치에 메타데이터 블록을 저장하기 때문입니다. instance 경우 JPEG와 TIFF는 모두 XMP 메타데이터 블록을 지원합니다. JPEG 이미지에서 XMP 블록은 WIC 메타데이터 개요에 설명된 대로 루트 메타데이터 블록에 있습니다. 그러나 TIFF 이미지에서 XMP 블록은 루트 IFD 블록에 중첩됩니다. 다음 다이어그램에서는 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 |
빠른 메타데이터 인코더 가져오기
메타데이터 패딩이 있는 이미지가 있는 경우 이미징 팩터리 메서드 CreateFastMetadataEncoderFromDecoder 및 CreateFastMetadataEncoderFromFrameDecode를 사용하여 빠른 메타데이터 인코더를 가져올 수 있습니다.
이름에서 알 수 있듯이 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();
}
}
어떤 이유로든 커밋 이 실패하면 이미지를 다시 인코딩하여 새 메타데이터가 이미지에 추가되도록 해야 합니다.
관련 항목