Add 4:1:1 subsampling support in the TurboJPEG C API

This commit is contained in:
DRC
2013-08-18 10:19:00 +00:00
parent 6bcd8f8345
commit 5ca8bf8738
9 changed files with 65 additions and 24 deletions

View File

@@ -10,6 +10,10 @@ extended to support image scaling.
MIPS platforms. This speeds up the compression of full-color JPEGs by 6-17%
on such platforms and decompression by 3-5%.
[3] Added support for 4:1:1 subsampling in the TurboJPEG API. This is mainly
included for compatibility, since 4:1:1 is not fully accelerated in
libjpeg-turbo and has no significant advantages relative to 4:2:0.
1.3.1
=====

View File

@@ -314,6 +314,11 @@ testclean:
rm -f *_440_*.ppm
rm -f *_440_*.jpg
rm -f *_440.yuv
rm -f *_411_*.bmp
rm -f *_411_*.png
rm -f *_411_*.ppm
rm -f *_411_*.jpg
rm -f *_411.yuv
tjtest:

View File

@@ -178,7 +178,8 @@ Enumerations</h2></td></tr>
<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737">TJSAMP_420</a>,
<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248">TJSAMP_GRAY</a>,
<br/>
&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974">TJSAMP_440</a>
&#160;&#160;<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974">TJSAMP_440</a>,
<a class="el" href="group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2">TJSAMP_411</a>
<br/>
}</td></tr>
<tr class="memdesc:ga1d047060ea80bb9820d540bb928e9074"><td class="mdescLeft">&#160;</td><td class="mdescRight">Chrominance subsampling options. <a href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">More...</a><br/></td></tr>
@@ -706,6 +707,10 @@ Variables</h2></td></tr>
<p>4:4:0 chrominance subsampling. </p>
<p>The JPEG or YUV image will contain one chrominance component for every 1x2 block of pixels in the source image. Note that 4:4:0 subsampling is not fully accelerated in libjpeg-turbo. </p>
</td></tr>
<tr><td class="fieldname"><em><a class="anchor" id="gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2"></a>TJSAMP_411</em>&nbsp;</td><td class="fielddoc">
<p>4:1:1 chrominance subsampling. </p>
<p>The JPEG or YUV image will contain one chrominance component for every 4x1 block of pixels in the source image. JPEG images compressed with 4:1:1 subsampling will be almost exactly the same size as those compressed with 4:2:0 subsampling, and in the aggregate, both subsampling methods produce approximately the same perceptual quality. However, 4:1:1 is better able to reproduce sharp horizontal features. Note that 4:1:1 subsampling is not fully accelerated in libjpeg-turbo. </p>
</td></tr>
</table>
</div>
@@ -1612,7 +1617,8 @@ If you choose option 1, <code>dstSizes[i]</code> should be set to the size of yo
<li>8x8 for no subsampling or grayscale</li>
<li>16x8 for 4:2:2</li>
<li>8x16 for 4:4:0</li>
<li>16x16 for 4:2:0 </li>
<li>16x16 for 4:2:0</li>
<li>32x8 for 4:1:1 </li>
</ul>
</div>
@@ -1641,7 +1647,8 @@ If you choose option 1, <code>dstSizes[i]</code> should be set to the size of yo
<li>8x8 for no subsampling or grayscale</li>
<li>16x8 for 4:2:2</li>
<li>8x16 for 4:4:0</li>
<li>16x16 for 4:2:0 </li>
<li>16x16 for 4:2:0</li>
<li>32x8 for 4:1:1 </li>
</ul>
</div>

View File

@@ -49,6 +49,7 @@ var searchData=
['tjredoffset',['tjRedOffset',['../group___turbo_j_p_e_g.html#gadd9b446742ac8a3923f7992c7988fea8',1,'turbojpeg.h']]],
['tjregion',['tjregion',['../structtjregion.html',1,'']]],
['tjsamp',['TJSAMP',['../group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074',1,'turbojpeg.h']]],
['tjsamp_5f411',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]],
['tjsamp_5f420',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]],
['tjsamp_5f422',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]],
['tjsamp_5f440',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]],
@@ -56,7 +57,7 @@ var searchData=
['tjsamp_5fgray',['TJSAMP_GRAY',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a3f1c9504842ddc7a48d0f690754b6248',1,'turbojpeg.h']]],
['tjscaled',['TJSCALED',['../group___turbo_j_p_e_g.html#ga84878bb65404204743aa18cac02781df',1,'turbojpeg.h']]],
['tjscalingfactor',['tjscalingfactor',['../structtjscalingfactor.html',1,'']]],
['tjtransform',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#gae403193ceb4aafb7e0f56ab587b48616',1,'tjTransform(tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags):&#160;turbojpeg.h'],['../group___turbo_j_p_e_g.html#gaa29f3189c41be12ec5dee7caec318a31',1,'tjtransform():&#160;turbojpeg.h']]],
['tjtransform',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#gaa29f3189c41be12ec5dee7caec318a31',1,'tjtransform():&#160;turbojpeg.h'],['../group___turbo_j_p_e_g.html#gae403193ceb4aafb7e0f56ab587b48616',1,'tjTransform(tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, int n, unsigned char **dstBufs, unsigned long *dstSizes, tjtransform *transforms, int flags):&#160;turbojpeg.h']]],
['tjxop',['TJXOP',['../group___turbo_j_p_e_g.html#ga2de531af4e7e6c4f124908376b354866',1,'turbojpeg.h']]],
['tjxop_5fhflip',['TJXOP_HFLIP',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aa0df69776caa30f0fa28e26332d311ce',1,'turbojpeg.h']]],
['tjxop_5fnone',['TJXOP_NONE',['../group___turbo_j_p_e_g.html#gga2de531af4e7e6c4f124908376b354866aad88c0366cd3f7d0eac9d7a3fa1c2c27',1,'turbojpeg.h']]],

View File

@@ -11,6 +11,7 @@ var searchData=
['tjpf_5frgbx',['TJPF_RGBX',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aa83973bebb7e2dc6fa8bae89ff3f42e01',1,'turbojpeg.h']]],
['tjpf_5fxbgr',['TJPF_XBGR',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aaf6603b27147de47e212e75dac027b2af',1,'turbojpeg.h']]],
['tjpf_5fxrgb',['TJPF_XRGB',['../group___turbo_j_p_e_g.html#ggac916144e26c3817ac514e64ae5d12e2aadae996905efcfa3b42a0bb3bea7f9d84',1,'turbojpeg.h']]],
['tjsamp_5f411',['TJSAMP_411',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a28ec62575e5ea295c3fde3001dc628e2',1,'turbojpeg.h']]],
['tjsamp_5f420',['TJSAMP_420',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a63085dbf683cfe39e513cdb6343e3737',1,'turbojpeg.h']]],
['tjsamp_5f422',['TJSAMP_422',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074a136130902cc578f11f32429b59368404',1,'turbojpeg.h']]],
['tjsamp_5f440',['TJSAMP_440',['../group___turbo_j_p_e_g.html#gga1d047060ea80bb9820d540bb928e9074accf740e6f3aa6ba20ba922cad13cb974',1,'turbojpeg.h']]],

View File

@@ -54,9 +54,9 @@ const char *pixFormatStr[TJ_NUMPF]=
};
const char *subNameLong[TJ_NUMSAMP]=
{
"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
};
const char *subName[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"};
const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440", "411"};
tjscalingfactor *scalingfactors=NULL, sf={1, 1}; int nsf=0;
int xformop=TJXOP_NONE, xformopt=0;
int (*customFilter)(short *, tjregion, tjregion, int, int, tjtransform *);
@@ -686,6 +686,7 @@ void usage(char *progname)
printf(" codec\n");
printf("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the\n");
printf(" underlying codec\n");
printf("-411 = Test 4:1:1 chrominance subsampling instead of 4:2:0\n");
printf("-440 = Test 4:4:0 chrominance subsampling instead of 4:2:2\n");
printf("-quiet = Output results in tabular rather than verbose format\n");
printf("-yuvencode = Encode RGB input as planar YUV rather than compressing as JPEG\n");
@@ -720,7 +721,7 @@ int main(int argc, char *argv[])
{
unsigned char *srcbuf=NULL; int w, h, i, j;
int minqual=-1, maxqual=-1; char *temp;
int minarg=2, retval=0, do440=0;
int minarg=2, retval=0, do440=0, do411=0;
if((scalingfactors=tjGetScalingFactors(&nsf))==NULL || nsf==0)
_throwtj("executing tjGetScalingFactors()");
@@ -858,6 +859,7 @@ int main(int argc, char *argv[])
if(!strcmp(argv[i], "-?")) usage(argv[0]);
if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC);
if(!strcasecmp(argv[i], "-bmp")) ext="bmp";
if(!strcasecmp(argv[i], "-411")) do411=1;
}
}
@@ -901,7 +903,7 @@ int main(int argc, char *argv[])
dotest(srcbuf, w, h, TJ_GRAYSCALE, i, argv[1]);
printf("\n");
for(i=maxqual; i>=minqual; i--)
dotest(srcbuf, w, h, TJ_420, i, argv[1]);
dotest(srcbuf, w, h, do411? TJSAMP_411:TJ_420, i, argv[1]);
printf("\n");
for(i=maxqual; i>=minqual; i--)
dotest(srcbuf, w, h, do440? TJSAMP_440:TJ_422, i, argv[1]);

View File

@@ -61,9 +61,9 @@ void usage(char *progName)
const char *subNameLong[TJ_NUMSAMP]=
{
"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
};
const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440"};
const char *subName[TJ_NUMSAMP]={"444", "422", "420", "GRAY", "440", "411"};
const char *pixFormatStr[TJ_NUMPF]=
{
@@ -472,7 +472,10 @@ void decompTest(tjhandle handle, unsigned char *jpegBuf,
for(i=0; i<n; i++)
{
if(subsamp==TJSAMP_444 || subsamp==TJSAMP_GRAY ||
(sf[i].num==1 && (sf[i].denom==4 || sf[i].denom==2 || sf[i].denom==1)))
(subsamp==TJSAMP_411 && sf[i].num==1 &&
(sf[i].denom==2 || sf[i].denom==1)) ||
(subsamp!=TJSAMP_411 && sf[i].num==1 &&
(sf[i].denom==4 || sf[i].denom==2 || sf[i].denom==1)))
_decompTest(handle, jpegBuf, jpegSize, w, h, pf, basename, subsamp,
flags, sf[i]);
}
@@ -505,7 +508,8 @@ void doTest(int w, int h, const int *formats, int nformats, int subsamp,
for(i=0; i<2; i++)
{
int flags=0;
if(subsamp==TJSAMP_422 || subsamp==TJSAMP_420 || subsamp==TJSAMP_440)
if(subsamp==TJSAMP_422 || subsamp==TJSAMP_420 || subsamp==TJSAMP_440 ||
subsamp==TJSAMP_411)
flags|=TJFLAG_FASTUPSAMPLE;
if(i==1)
{
@@ -631,9 +635,11 @@ int main(int argc, char *argv[])
doTest(41, 35, _4byteFormats, 4, TJSAMP_420, "test");
doTest(35, 39, _3byteFormats, 2, TJSAMP_440, "test");
doTest(39, 41, _4byteFormats, 4, TJSAMP_440, "test");
doTest(35, 39, _onlyGray, 1, TJSAMP_GRAY, "test");
doTest(39, 41, _3byteFormats, 2, TJSAMP_GRAY, "test");
doTest(41, 35, _4byteFormats, 4, TJSAMP_GRAY, "test");
doTest(41, 35, _3byteFormats, 2, TJSAMP_411, "test");
doTest(35, 39, _4byteFormats, 4, TJSAMP_411, "test");
doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test");
doTest(41, 35, _3byteFormats, 2, TJSAMP_GRAY, "test");
doTest(35, 39, _4byteFormats, 4, TJSAMP_GRAY, "test");
if(!doyuv) bufSizeTest();
if(doyuv)
{
@@ -646,10 +652,12 @@ int main(int argc, char *argv[])
doTest(41, 35, _onlyRGB, 1, TJSAMP_420, "test_yuv1");
doTest(48, 48, _onlyRGB, 1, TJSAMP_440, "test_yuv0");
doTest(35, 39, _onlyRGB, 1, TJSAMP_440, "test_yuv1");
doTest(48, 48, _onlyRGB, 1, TJSAMP_411, "test_yuv0");
doTest(39, 41, _onlyRGB, 1, TJSAMP_411, "test_yuv1");
doTest(48, 48, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv0");
doTest(35, 39, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv1");
doTest(41, 35, _onlyRGB, 1, TJSAMP_GRAY, "test_yuv1");
doTest(48, 48, _onlyGray, 1, TJSAMP_GRAY, "test_yuv0");
doTest(39, 41, _onlyGray, 1, TJSAMP_GRAY, "test_yuv1");
doTest(35, 39, _onlyGray, 1, TJSAMP_GRAY, "test_yuv1");
}
return exitStatus;

View File

@@ -87,7 +87,7 @@ typedef struct _tjinstance
int init;
} tjinstance;
static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3};
static const int pixelsize[TJ_NUMSAMP]={3, 3, 3, 1, 3, 3};
static const JXFORM_CODE xformtypes[TJ_NUMXOP]=
{

View File

@@ -49,7 +49,7 @@
/**
* The number of chrominance subsampling options
*/
#define TJ_NUMSAMP 5
#define TJ_NUMSAMP 6
/**
* Chrominance subsampling options.
@@ -87,7 +87,18 @@ enum TJSAMP
* chrominance component for every 1x2 block of pixels in the source image.
* Note that 4:4:0 subsampling is not fully accelerated in libjpeg-turbo.
*/
TJSAMP_440
TJSAMP_440,
/**
* 4:1:1 chrominance subsampling. The JPEG or YUV image will contain one
* chrominance component for every 4x1 block of pixels in the source image.
* JPEG images compressed with 4:1:1 subsampling will be almost exactly the
* same size as those compressed with 4:2:0 subsampling, and in the
* aggregate, both subsampling methods produce approximately the same
* perceptual quality. However, 4:1:1 is better able to reproduce sharp
* horizontal features. Note that 4:1:1 subsampling is not fully accelerated
* in libjpeg-turbo.
*/
TJSAMP_411
};
/**
@@ -96,9 +107,10 @@ enum TJSAMP
* - 8x8 for no subsampling or grayscale
* - 16x8 for 4:2:2
* - 8x16 for 4:4:0
* - 16x16 for 4:2:0
* - 16x16 for 4:2:0
* - 32x8 for 4:1:1
*/
static const int tjMCUWidth[TJ_NUMSAMP] = {8, 16, 16, 8, 8};
static const int tjMCUWidth[TJ_NUMSAMP] = {8, 16, 16, 8, 8, 32};
/**
* MCU block height (in pixels) for a given level of chrominance subsampling.
@@ -106,9 +118,10 @@ static const int tjMCUWidth[TJ_NUMSAMP] = {8, 16, 16, 8, 8};
* - 8x8 for no subsampling or grayscale
* - 16x8 for 4:2:2
* - 8x16 for 4:4:0
* - 16x16 for 4:2:0
* - 16x16 for 4:2:0
* - 32x8 for 4:1:1
*/
static const int tjMCUHeight[TJ_NUMSAMP] = {8, 8, 16, 8, 16};
static const int tjMCUHeight[TJ_NUMSAMP] = {8, 8, 16, 8, 16, 8};
/**