我一直在 Silverlight 项目中使用FJCore库来帮助进行一些实时图像处理,并且我试图弄清楚如何从库中获得更多的压缩和性能。现在,据我了解,JPEG 标准允许您指定色度子采样率(请参阅http://en.wikipedia.org/wiki/Chroma_subsampling和http://en.wikipedia.org/wiki/Jpeg);看来这应该在 FJCore 库中使用 HsampFactor 和 VsampFactor 数组来实现:
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,它只是抓取两个块而不是一个块。