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
=====
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:
<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/>
-  <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#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"> </td><td class="mdescRight">Chrominance subsampling options. <a href="group___turbo_j_p_e_g.html#ga1d047060ea80bb9820d540bb928e9074">More...</a><br/></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> </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>
<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>
<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>
['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']]],
['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): turbojpeg.h'],['../group___turbo_j_p_e_g.html#gaa29f3189c41be12ec5dee7caec318a31',1,'tjtransform(): turbojpeg.h']]],
+ ['tjtransform',['tjtransform',['../structtjtransform.html',1,'tjtransform'],['../group___turbo_j_p_e_g.html#gaa29f3189c41be12ec5dee7caec318a31',1,'tjtransform(): 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): 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']]],
['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']]],
};
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 *);
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");
{
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()");
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;
}
}
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]);
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]=
{
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]);
}
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)
{
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)
{
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;
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]=
{
/**
* The number of chrominance subsampling options
*/
-#define TJ_NUMSAMP 5
+#define TJ_NUMSAMP 6
/**
* Chrominance subsampling options.
* 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
};
/**
* - 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.
* - 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};
/**