次の方法で共有


エンコードの概要

エンコーダーは、画像データをストリームに書き込みます。 エンコーダーは、ストリームに書き込む前に、さまざまな方法で画像ピクセルを圧縮、暗号化、および変更できます。 一部のエンコーダーを使用すると、JPEG などのトレードオフが生じ、色情報がトレードオフされ、圧縮が向上します。 他のエンコーダーでは、ビットマップ (BMP) などの損失は発生しません。 多くのコーデックでは独自のテクノロジを使用して、圧縮と画像の忠実性が向上するため、画像のエンコード方法の詳細はコーデック開発者が行います。

IWICBitmapEncoder

IWICBitmapEncoder は、イメージをターゲット形式にエンコードするためのメイン インターフェイスであり、サムネイル (SetThumbnail) やフレーム (CreateNewFrame) などのイメージのコンポーネントをイメージ ファイルにシリアル化するために使用されます。

シリアル化が発生する方法とタイミングは、コーデック開発者に任されています。 ターゲット ファイル形式内の個々のデータ ブロックは、順序に依存せず設定できる必要がありますが、これはコーデック開発者の決定です。 ただし、 Commit メソッドが呼び出されると、イメージへの変更を許可せず、ストリームを閉じる必要があります。

IWICBitmapFrameEncode

IWICBitmapFrameEncode は、イメージの個々のフレームをエンコードするためのインターフェイスです。 サムネイルやフレームなどの個々のフレーム イメージング コンポーネントを設定する方法と、画像のサイズ、DPI、ピクセル形式を提供します。

個々のフレームはフレーム固有のメタデータでエンコードできるため、 IWICBitmapFrameEncodeGetMetadataQueryWriter メソッドを使用してメタデータ ライターにアクセスできます。

フレームの Commit メソッドは、個々のフレームに対するすべての変更をコミットし、そのフレームへの変更を受け入れないことを示します。

エンコードの例 (TIFF)

次の例では、タグ付きイメージ ファイル形式 (TIFF) イメージは 、IWICBitmapEncoderIWICBitmapFrameEncode を使用してエンコードされます。 TIFF 出力は WICTiffCompressionOption を使用してカスタマイズされ、ビットマップ フレームは指定されたオプションを使用して初期化されます。 WritePixels を使用してイメージが作成されると、フレームは Commit を使用してコミットされ、イメージは Commit を使用して保存されます。

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;

エンコーダー オプションの使用方法

異なる形式の異なるエンコーダーでは、イメージのエンコード方法に関するさまざまなオプションを公開する必要があります。 Windows イメージング コンポーネント (WIC) は、特定の形式に関する知識がなくてもアプリケーションが複数のエンコーダーを操作できるようにしながら、エンコード オプションが必要かどうかを表現するための一貫したメカニズムを提供します。 これを行うには、CreateNewFrame メソッドと Initialize メソッドに IPropertyBag パラメーターを指定します。

コンポーネント ファクトリは、エンコーダー オプション プロパティ バッグを作成するための簡単な作成ポイントを提供します。 コーデックは、シンプルで直感的で競合しない一連のエンコーダー オプションを提供する必要がある場合に、このサービスを使用できます。 イメージング プロパティ バッグは、作成時に、そのコーデックに関連するすべてのエンコーダー オプションを使用して初期化する必要があります。 正規セットのエンコーダー オプションの場合、値の範囲は書き込み時に適用されます。 より高度なニーズのために、コーデックは独自のプロパティ バッグの実装を記述する必要があります。

アプリケーションには、フレームの作成時にエンコーダー オプション バッグが与えられ、エンコーダー フレームを初期化する前に値を構成する必要があります。 UI 駆動型アプリケーションの場合は、正規エンコーダー オプション用の固定 UI と、残りのオプションの詳細ビューを提供できます。 変更は Write メソッドを通じて一度に 1 つずつ行うことができます。エラーは IErrorLog を通じて報告されます。 変更によって連鎖効果が発生した場合は、変更を行った後、UI アプリケーションは常にすべてのオプションを再読み取りして表示する必要があります。 アプリケーションは、プロパティ バッグを介して報告する最小限のエラーのみを提供するコーデックのフレーム初期化の失敗を処理するように準備する必要があります。

エンコーダー オプション

アプリケーションでは、次の一連のエンコーダー オプションが発生する可能性があります。 エンコーダー オプションは、エンコーダーの機能と基になるコンテナー形式を反映しているため、その性質上、コーデックに依存しません。 可能であれば、新しいオプションを正規化して、出現する新しいコーデックに適用できるようにする必要があります。

プロパティ名 VARTYPE 価値 適用可能なコーデック
ビットマップ変換 VT_UI1 WICBitmapTransformOptions JPEG、JPEG XL、HEIF
圧縮品質 VT_R4 0-1.0 TIFF、JPEG XL
HEIF圧縮方式 VT_UI1 WICHeifCompressionOption HEIF
ImageQuality VT_R4 0-1.0 JPEG、JPEG XL、HDPhoto、HEIF
ロスレス VT_BOOL TRUEFALSE JPEG XL、HDPhoto

ImageQualty 0.0 は、可能な限り最も低い忠実度表示を意味し、1.0 は最も忠実度が高く、コーデックによってはロスレスを意味する場合もあります。

CompressionQuality が 0.0 の場合は、使用可能な圧縮方式が最も効率が低いことを意味し、通常は高速エンコードで出力が大きくなります。 値が 1.0 の場合は、使用可能な最も効率的なスキームを意味します。通常、エンコードに時間がかかり、出力が小さくなります。 コーデックの機能に応じて、この範囲は、使用可能な圧縮方法の個別のセットにマップされる場合があります。

ロスレスとは、コーデックがイメージをロスレスとしてエンコードし、画像データを失う必要がないことを意味します。 Lossless が有効になっている場合、ImageQuality は無視されます。

上記の汎用エンコーダー オプションに加えて、WIC で提供されるコーデックでは、次のオプションがサポートされます。 コーデックで、これらの提供されたコーデックでの使用と一致するオプションをサポートする必要がある場合は、これを行うことをお勧めします。

プロパティ名 VARTYPE 価値 適用可能なコーデック
InterlaceOption VT_BOOL オン/オフ PNG
フィルターオプション VT_UI1 WICPngFilterOption PNG
TIFF圧縮方法 VT_UI1 WICTiffCompressionOption TIFF (画像ファイル形式)
輝度 VT_UI4/VT_ARRAY 64 エントリ (DCT) JPEG
クロミナンス VT_UI4/VT_ARRAY 64 エントリ (DCT) JPEG
JpegYCrCbサブサンプリング VT_UI1 WICJpegYCrCbSubsamplingOption JPEG
SuppressApp0 VT_BOOL JPEG
EnableV5Header32bppBGRA VT_BOOL オン/オフ BMP

既定値として *not set* を指定するには、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);
    }
}