]> granicus.if.org Git - libjpeg-turbo/commitdiff
Add 4:1:1 subsampling support in the TurboJPEG C API
authorDRC <dcommander@users.sourceforge.net>
Sun, 18 Aug 2013 10:19:00 +0000 (10:19 +0000)
committerDRC <dcommander@users.sourceforge.net>
Sun, 18 Aug 2013 10:19:00 +0000 (10:19 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1014 632fc199-4ca6-4c93-a231-07263d6284db

ChangeLog.txt
Makefile.am
doc/html/group___turbo_j_p_e_g.html
doc/html/search/all_74.js
doc/html/search/enumvalues_74.js
tjbench.c
tjunittest.c
turbojpeg.c
turbojpeg.h

index caea39f7aed279929ad9c0060b00d7698b870089..f2ff88d4daf9069b166eb74e7e9a2f33e72f3589 100644 (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
 =====
index de6c3073654b164fd0a85300c88e73fdf646cb5e..6096049b3cf44a60daafe25ba6a7819c8b69ecab 100644 (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:
index 052e750f5ddac2845b184e300adb3c6b20f2dc4c..26c7768be8b9720e02c207f951789e0d6b1dcdca 100644 (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>
index 4c7c2333bedc245c2d641f4e1dd52c0007612fcd..01c414a9e2f875045a19e6b4270c25bc3a08e9cc 100644 (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']]],
index 55664f1630fc98e7b7da66ba342db8ac681e7eea..16e7e15fb287d070ff616434ba6b9b889a494f76 100644 (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']]],
index 105a4ccec43fe1d415ebcc877337d296cf7dbe18..10a0f266efb61659d4f2518a32ec34b495989b6d 100644 (file)
--- a/tjbench.c
+++ b/tjbench.c
@@ -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]);
index c14c7d3248cc7444faa6592318a82d9ad98c784c..29ed90da47b904b99c19dc9939b1009a20b0f068 100644 (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;
index e53cf667fd8b3954ea0d1666d152da2053fdf3e4..94918c99174007bc655d45b0da88311588562556 100644 (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]=
 {
index 66be1d87e7a98fc78b62f770d112eb48a0a13a47..668a50a68919d9807e0cc4b88320d4b91a0ba716 100644 (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};
 
 
 /**