私は、Silverlight プロジェクトでFJCoreライブラリを使用して、リアルタイムの画像処理を支援してきました。ライブラリから圧縮とパフォーマンスを少し高める方法を見つけようとしています。現在、私が理解しているように、JPEG 標準ではクロマ サブサンプリング比を指定できます ( http://en.wikipedia.org/wiki/Chroma_subsamplingおよびhttp://en.wikipedia.org/wiki/Jpegを参照)。これは、HsampFactor および VsampFactor 配列を使用して FJCore ライブラリに実装されることになっているようです。
public static readonly byte[] HsampFactor = { 1, 1, 1 };
public static readonly byte[] VsampFactor = { 1, 1, 1 };
しかし、私はそれらを使用する方法を理解するのに苦労しています。現在の値は 4:4:4 サブサンプリング (たとえば、サブサンプリングがまったくない) を表しているように見えますが、4:1:1 サブサンプリングを取得したい場合、正しい値は次のようになります。
public static readonly byte[] HsampFactor = { 2, 1, 1 };
public static readonly byte[] VsampFactor = { 2, 1, 1 };
少なくとも、これは他の同様のライブラリがこれらの値を使用する方法です (たとえば、libjpeg のサンプル コードはこちらを参照してください)。
ただし、上記の {2, 1, 1} の値も、{1, 1, 1} 以外に試した他の値のセットも、判読可能な画像を生成しません。また、コードを見ると、そのように書かれているようには見えません。しかし、私の人生では、FJCore コードが実際に何をしようとしているのか理解できません。サンプル係数を使用して、既に実行されている操作を繰り返しているようです。つまり、よくわからない場合は、バグだと思います。しかし、これはかなり確立された Java コードに基づいた、かなり確立されたライブラリなので、もしそうだとしたら驚きです。
これらの値を使用して 4:2:2 または 4:1:1 クロマ サブサンプリングを取得する方法について何か提案はありますか?
価値のあるものとして、JpegEncoderクラスの関連コードを次に示します。
for (comp = 0; comp < _input.Image.ComponentCount; comp++)
{
Width = _input.BlockWidth[comp];
Height = _input.BlockHeight[comp];
inputArray = _input.Image.Raster[comp];
for (i = 0; i < _input.VsampFactor[comp]; i++)
{
for (j = 0; j < _input.HsampFactor[comp]; j++)
{
xblockoffset = j * 8;
yblockoffset = i * 8;
for (a = 0; a < 8; a++)
{
// set Y value. check bounds
int y = ypos + yblockoffset + a; if (y >= _height) break;
for (b = 0; b < 8; b++)
{
int x = xpos + xblockoffset + b; if (x >= _width) break;
dctArray1[a, b] = inputArray[x, y];
}
}
dctArray2 = _dct.FastFDCT(dctArray1);
dctArray3 = _dct.QuantizeBlock(dctArray2, FrameDefaults.QtableNumber[comp]);
_huf.HuffmanBlockEncoder(buffer, dctArray3, lastDCvalue[comp], FrameDefaults.DCtableNumber[comp], FrameDefaults.ACtableNumber[comp]);
lastDCvalue[comp] = dctArray3[0];
}
}
}
また、i & j ループでは、ピクセル スキップを制御していないことに注意してください。HsampFactor[0] が 2 に設定されている場合、1 つではなく 2 つのブロックを取得しているだけです。