다음을 통해 공유


인코딩 개요

Important

일부 정보는 상용 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.

인코더는 이미지 데이터를 스트림에 씁니다. 인코더는 이미지 픽셀을 스트림에 쓰기 전에 여러 가지 방법으로 압축, 암호화 및 변경할 수 있습니다. 일부 인코더를 사용하면 더 나은 압축을 위해 색 정보를 절충하는 JPEG와 같은 절충이 발생합니다. 다른 인코더는 BMP(비트맵)와 같은 손실을 초래하지 않습니다. 많은 코덱이 독점 기술을 사용하여 더 나은 압축 및 이미지 충실도를 달성하기 때문에 이미지가 인코딩되는 방법에 대한 세부 정보는 코덱 개발자에게 달려 있습니다.

IWICBitmapEncoder

IWICBitmapEncoder는 이미지를 대상 형식으로 인코딩하기 위한 기본 인터페이스이며 썸네일(SetThumbnail) 및 프레임(CreateNewFrame)과 같은 이미지의 구성 요소를 이미지 파일에 직렬화하는 데 사용됩니다.

serialization이 발생하는 방법과 시기는 코덱 개발자에게 맡깁니다. 대상 파일 형식 내의 각 개별 데이터 블록은 순서에 관계없이 설정할 수 있어야 하지만, 다시 코덱 개발자의 결정입니다. 그러나 Commit 메서드가 호출되면 이미지 변경이 허용되지 않아야 하며 스트림을 닫아야 합니다.

IWICBitmapFrameEncode

IWICBitmapFrameEncode 는 이미지의 개별 프레임을 인코딩하기 위한 인터페이스입니다. 썸네일 및 프레임과 같은 개별 프레임 이미징 구성 요소뿐만 아니라 이미지 차원, DPI 및 픽셀 형식을 설정하는 메서드를 제공합니다.

개별 프레임은 프레임별 메타데이터로 인코딩될 수 있으므로 IWICBitmapFrameEncode 는 GetMetadataQueryWriter 메서드를 통해 메타데이터 작성기에 대한 액세스를 제공합니다.

프레임의 Commit 메서드는 개별 프레임에 대한 모든 변경 내용을 커밋하고 해당 프레임의 변경 내용을 더 이상 수락하지 않음을 나타냅니다.

인코딩 예제(TIFF)

다음 예제에서는 TIFF(태그가 지정된 이미지 파일 형식) 이미지가 IWICBitmapEncoder 및 IWICBitmapFrameEncode사용하여 인코딩됩니다. TIFF 출력은 WICTiffCompressionOption을 사용하여 사용자 지정되며 비트맵 프레임은 지정된 옵션을 사용하여 초기화됩니다. WritePixels를 사용하여 이미지를 만든 후에는 커밋을 통해 프레임이 커밋되고 커밋을 사용하여 이미지가 저장됩니다.

IWICImagingFactory *piFactory = NULL;
IWICBitmapEncoder *piEncoder = NULL;
IWICBitmapFrameEncode *piBitmapFrame = NULL;
IPropertyBag2 *pPropertybag = NULL;

IWICStream *piStream = NULL;
UINT uiWidth = 640;
UINT uiHeight = 480;

HRESULT hr = CoCreateInstance(
                CLSID_WICImagingFactory,
                NULL,
                CLSCTX_INPROC_SERVER,
                IID_IWICImagingFactory,
                (LPVOID*) &piFactory);

if (SUCCEEDED(hr))
{
    hr = piFactory->CreateStream(&piStream);
}

if (SUCCEEDED(hr))
{
    hr = piStream->InitializeFromFilename(L"output.tif", GENERIC_WRITE);
}

if (SUCCEEDED(hr))
{
   hr = piFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &piEncoder);
}

if (SUCCEEDED(hr))
{
    hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
}

if (SUCCEEDED(hr))
{
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}

if (SUCCEEDED(hr))
{        
    // This is how you customize the TIFF output.
    PROPBAG2 option = { 0 };
    option.pstrName = L"TiffCompressionMethod";
    VARIANT varValue;    
    VariantInit(&varValue);
    varValue.vt = VT_UI1;
    varValue.bVal = WICTiffCompressionZIP;      
    hr = pPropertybag->Write(1, &option, &varValue);        
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(pPropertybag);
    }
}

if (SUCCEEDED(hr))
{
    hr = piBitmapFrame->SetSize(uiWidth, uiHeight);
}

WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR;
if (SUCCEEDED(hr))
{
    hr = piBitmapFrame->SetPixelFormat(&formatGUID);
}

if (SUCCEEDED(hr))
{
    // We're expecting to write out 24bppRGB. Fail if the encoder cannot do it.
    hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL;
}

if (SUCCEEDED(hr))
{
    UINT cbStride = (uiWidth * 24 + 7)/8/***WICGetStride***/;
    UINT cbBufferSize = uiHeight * cbStride;

    BYTE *pbBuffer = new BYTE[cbBufferSize];

    if (pbBuffer != NULL)
    {
        for (UINT i = 0; i < cbBufferSize; i++)
        {
            pbBuffer[i] = static_cast<BYTE>(rand());
        }

        hr = piBitmapFrame->WritePixels(uiHeight, cbStride, cbBufferSize, pbBuffer);

        delete[] pbBuffer;
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }
}

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

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

if (piFactory)
    piFactory->Release();

if (piEncoder)
    piEncoder->Release();

if (piBitmapFrame)
    piBitmapFrame->Release();

if (pPropertybag)
    pPropertybag->Release();

if (piStream)
    piStream->Release();

return hr;

인코더 옵션 사용

다른 형식에 대한 다른 인코더는 이미지를 인코딩하는 방법에 대한 다양한 옵션을 노출해야 합니다. WIC(Windows 이미징 구성 요소)는 애플리케이션이 특정 형식에 대한 지식 없이도 여러 인코더로 작업할 수 있도록 하면서 인코딩 옵션이 필요한지 여부를 나타내는 일관된 메커니즘을 제공합니다. CreateNewFrame 메서드 및 Initialize 메서드에 IPropertyBag 매개 변수를 제공하여 이 작업을 수행합니다.

구성 요소 팩터리는 인코더 옵션 속성 모음을 만들기 위한 간편한 생성 지점을 제공합니다. 코덱은 간단하고 직관적이며 충돌하지 않는 인코더 옵션 집합을 제공해야 하는 경우 이 서비스를 사용할 수 있습니다. 이미징 속성 모음은 생성 중에 해당 코덱과 관련된 모든 인코더 옵션을 사용하여 초기화해야 합니다. 정식 집합의 인코더 옵션의 경우 값 범위는 쓰기에 적용됩니다. 고급 요구 사항을 위해 코덱은 자체 속성 모음 구현을 작성해야 합니다.

애플리케이션은 프레임을 만드는 동안 인코더 옵션 모음을 제공하며 인코더 프레임을 초기화하기 전에 값을 구성해야 합니다. UI 기반 애플리케이션의 경우 정식 인코더 옵션에 대한 고정 UI와 다시 기본 옵션에 대한 고급 보기를 제공할 수 있습니다. Write 메서드를 통해 한 번에 하나씩 변경될 수 있으며 모든 오류는 IErrorLog를 통해 보고됩니다. 변경으로 인해 계단식 효과가 발생할 경우 UI 애플리케이션은 항상 다시 읽고 모든 옵션을 표시해야 합니다. 애플리케이션은 속성 모음을 통해 최소한의 오류 보고만 제공하는 코덱에 대해 실패한 프레임 초기화를 처리하도록 준비해야 합니다.

인코더 옵션

애플리케이션에는 다음 인코더 옵션 집합이 발생할 수 있습니다. 인코더 옵션은 인코더의 기능과 기본 컨테이너 형식을 반영하므로 본질적으로 코덱에 구애받지 않습니다. 가능하면 새로운 옵션이 나타나는 새 코덱에 적용할 수 있도록 정규화되어야 합니다.

속성 이름 VARTYPE 적용 가능한 코덱
BitmapTransform VT_UI1 WICBitmapTransformOptions JPEG, HEIF
CompressionQuality VT_R4 0-1.0 TIFF
HeifCompressionMethod WICHeifCompressionOption 다양함 HEIF
ImageQuality VT_R4 0-1.0 JPEG, HDPhoto, HEIF
무손실 VT_BOOL TRUE, FALSE HDPhoto

ImageQualty 0.0은 가능한 가장 낮은 충실도 변환을 의미하고 1.0은 가장 높은 충실도를 의미하며 코덱에 따라 무손실을 암시할 수도 있습니다.

CompressionQuality가 0.0이면 사용 가능한 가장 효율적인 압축 체계를 의미하며, 일반적으로 인코딩 속도가 빠르지만 출력이 더 큽니다. 값 1.0은 사용 가능한 가장 효율적인 체계를 의미하며, 일반적으로 인코딩하는 데 더 많은 시간이 걸리지만 더 작은 출력을 생성합니다. 코덱의 기능에 따라 이 범위는 사용 가능한 개별 압축 메서드 집합에 매핑될 수 있습니다.

손실 없음은 코덱이 이미지 데이터 손실 없이 이미지를 무손실로 인코딩한다는 것을 의미합니다. Lossless를 사용하도록 설정하면 ImageQuality가 무시됩니다.

위의 제네릭 인코더 옵션 외에도 WIC와 함께 제공되는 코덱은 다음 옵션을 지원합니다. 코덱이 이러한 제공된 코덱의 사용량과 일치하는 옵션을 지원해야 하는 경우 이를 수행하는 것이 좋습니다.

속성 이름 VARTYPE 적용 가능한 코덱
InterlaceOption VT_BOOL 켜기/끄기 PNG
FilterOption VT_UI1 WICPngFilterOption PNG
TiffCompressionMethod VT_UI1 WICTiffCompressionOption TIFF
광도 VT_UI4/VT_ARRAY 64개 항목(DCT) JPEG
색차 VT_UI4/VT_ARRAY 64개 항목(DCT) JPEG
JpegYCrCbSubsampling VT_UI1 WICJpegYCrCbSubsamplingOption JPEG
SuppressApp0 VT_BOOL JPEG
EnableV5Header32bppBGRA VT_BOOL 켜기/끄기 BMP

VT_EMPTY 사용하여 *설정 안 됨*을 기본값으로 표시합니다. 추가 속성이 설정되었지만 지원되지 않는 경우 인코더는 무시해야 합니다. 이렇게 하면 애플리케이션이 존재할 수도 있거나 없을 수도 있는 기능을 원하는 경우 더 적은 논리를 코딩할 수 있습니다.

인코더 옵션 예제

위의 TIFF 인코딩 예제에서 특정 인코더 옵션이 설정됩니다. PROPBAG2 구조체의 pstrName 멤버는 적절한 속성 이름으로 설정되고 VARIANT는 해당 VARTYPE 및 원하는 값(이 경우 WICTiffCompressionOption 열거형의 멤버)으로 설정됩니다.

if (SUCCEEDED(hr))
{
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}

if (SUCCEEDED(hr))
{        
    // This is how you customize the TIFF output.
    PROPBAG2 option = { 0 };
    option.pstrName = L"TiffCompressionMethod";
    VARIANT varValue;    
    VariantInit(&varValue);
    varValue.vt = VT_UI1;
    varValue.bVal = WICTiffCompressionZIP;      
    hr = pPropertybag->Write(1, &option, &varValue);        
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(pPropertybag);
    }
}

기본 인코더 옵션을 사용하려면 프레임을 만들 때 반환된 속성 모음을 사용하여 비트맵 프레임을 초기화하기만 하면됩니다.

if (SUCCEEDED(hr))
{
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}

if (SUCCEEDED(hr))
{        
    // Accept the default encoder options.
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(pPropertybag);
    }
}

인코더 옵션을 고려하지 않을 때 속성 모음을 제거할 수도 있습니다.

if (SUCCEEDED(hr))
{
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, 0);
}

if (SUCCEEDED(hr))
{        
    // No encoder options.
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(0);
    }
}