エンコードの概要
エンコーダーは、イメージ データをストリームに書き込みます。 エンコーダーは、ストリームに書き込む前に、さまざまな方法で画像ピクセルを圧縮、暗号化、および変更できます。 一部のエンコーダーを使用すると、JPEG などのトレードオフが生じ、色情報がトレードオフされ、圧縮が向上します。 他のエンコーダーでは、ビットマップ (BMP) など、このような損失は発生しません。 多くのコーデックでは、圧縮と画像の忠実性を向上させるために独自のテクノロジを使用しているため、画像のエンコード方法の詳細はコーデック開発者にかかっています。
このトピックのセクションは次のとおりです。
- IWICBitmapEncoder
- IWICBitmapFrameEncode
- TIFF エンコードの例
- エンコーダー オプションの使用法
- エンコーダー のオプション
- エンコーダー オプションの例
- 関連トピック
IWICBitmapEncoder
IWICBitmapEncoder は、イメージをターゲット形式にエンコードするためのメイン インターフェイスであり、サムネイル (SetThumbnail) やフレーム (CreateNewFrame) などのイメージのコンポーネントをイメージ ファイルにシリアル化するために使用されます。
シリアル化が発生する方法とタイミングは、コーデック開発者に任されます。 ターゲット ファイル形式内の個々のデータ ブロックは、順序に依存せず設定できる必要がありますが、これはコーデック開発者の決定です。 ただし、 Commit メソッドが呼び出されると、イメージへの変更を許可せず、ストリームを閉じる必要があります。
IWICBitmapFrameEncode
IWICBitmapFrameEncode は、イメージの個々のフレームをエンコードするためのインターフェイスです。 サムネイルやフレームなどの個々のフレーム イメージング コンポーネントを設定する方法と、画像のサイズ、DPI、ピクセル形式を設定する方法を提供します。
個々のフレームはフレーム固有のメタデータでエンコードされる可能性があるため、 IWICBitmapFrameEncode は GetMetadataQueryWriter メソッドを使用してメタデータ ライターにアクセスできます。
フレームの Commit メソッドは、個々のフレームに対するすべての変更をコミットし、そのフレームへの変更を受け入れないことを示します。
TIFF エンコードの例
次の例では、タグ付けされたイメージ ファイル形式 (TIFF) イメージは 、IWICBitmapEncoder と IWICBitmapFrameEncode を使用してエンコードされます。 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 | 値 | 適用可能なコーデック |
---|---|---|---|
ImageQuality | VT_R4 | 0-1.0 | JPEG、HDPhoto |
CompressionQuality | VT_R4 | 0-1.0 | TIFF |
ロスレス | VT_BOOL | TRUE、 FALSE | HDPhoto |
BitmapTransform | VT_UI1 | WICBitmapTransformOptions | JPEG |
ImageQualty 0.0 は、可能な限り忠実度が最も低い表示を意味し、1.0 は最高の忠実性を意味します。これは、コーデックによってはロスレスを意味する場合もあります。
CompressionQuality 0.0 は、使用できる圧縮スキームの効率が最も低いことを意味し、通常は高速エンコードされますが、出力が大きくなります。 値 1.0 は、使用可能な最も効率的なスキームを意味します。通常、エンコードに時間がかかり、出力が小さくなります。 コーデックの機能に応じて、この範囲は、使用可能な圧縮方法の個別のセットにマップされる場合があります。
ロスレスとは、コーデックがイメージをロスレスとしてエンコードし、イメージ データを失う必要がないことを意味します。 ロスレスが有効になっている場合、ImageQuality は無視されます。
上記の汎用エンコーダー オプションに加えて、WIC で提供されるコーデックでは、次のオプションがサポートされます。 コーデックで、これらの提供されているコーデックでの使用と一致するオプションをサポートする必要がある場合は、そのオプションをサポートすることをお勧めします。
プロパティ名 | VARTYPE | 値 | 適用可能なコーデック |
---|---|---|---|
InterlaceOption | VT_BOOL | オン/オフ | PNG |
FilterOption | VT_UI1 | WICPngFilterOption | PNG |
TiffCompressionMethod | VT_UI1 | WICTiffCompressionOption | TIFF |
Luminance | VT_UI4/VT_ARRAY | 64 エントリ (DCT) | JPEG |
Chrominance | VT_UI4/VT_ARRAY | 64 エントリ (DCT) | JPEG |
JpegYCrCbSubsampling | 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);
}
}
関連トピック