Handle 4:4:0 (transposed 4:2:2 subsampling)

git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@502 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
DRC
2011-03-04 12:52:45 +00:00
parent e85730157e
commit a3f68b4d2a
4 changed files with 35 additions and 26 deletions

View File

@@ -22,8 +22,8 @@
#define _catch(f) {if((f)==-1) {printf("TJPEG: %s\n", tjGetErrorStr()); bailout();}} #define _catch(f) {if((f)==-1) {printf("TJPEG: %s\n", tjGetErrorStr()); bailout();}}
const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"}; const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"};
const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"}; const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"};
#define NUMPF 7 #define NUMPF 7
enum {RGB=0, BGR, RGBX, BGRX, XBGR, XRGB, GRAY}; enum {RGB=0, BGR, RGBX, BGRX, XBGR, XRGB, GRAY};
@@ -576,6 +576,8 @@ int main(int argc, char *argv[])
dotest(35, 39, _4byteformats, 4, TJ_422, "test"); dotest(35, 39, _4byteformats, 4, TJ_422, "test");
dotest(39, 41, _3byteformats, 2, TJ_420, "test"); dotest(39, 41, _3byteformats, 2, TJ_420, "test");
dotest(41, 35, _4byteformats, 4, TJ_420, "test"); dotest(41, 35, _4byteformats, 4, TJ_420, "test");
dotest(35, 39, _3byteformats, 2, TJ_440, "test");
dotest(39, 41, _4byteformats, 4, TJ_440, "test");
} }
dotest(35, 39, _onlygray, 1, TJ_GRAYSCALE, "test"); dotest(35, 39, _onlygray, 1, TJ_GRAYSCALE, "test");
dotest(39, 41, _3byteformats, 2, TJ_GRAYSCALE, "test"); dotest(39, 41, _3byteformats, 2, TJ_GRAYSCALE, "test");
@@ -590,6 +592,8 @@ int main(int argc, char *argv[])
dotest(39, 41, _onlyrgb, 1, TJ_422, "test_yuv1"); dotest(39, 41, _onlyrgb, 1, TJ_422, "test_yuv1");
dotest(48, 48, _onlyrgb, 1, TJ_420, "test_yuv0"); dotest(48, 48, _onlyrgb, 1, TJ_420, "test_yuv0");
dotest(41, 35, _onlyrgb, 1, TJ_420, "test_yuv1"); dotest(41, 35, _onlyrgb, 1, TJ_420, "test_yuv1");
dotest(48, 48, _onlyrgb, 1, TJ_440, "test_yuv0");
dotest(35, 39, _onlyrgb, 1, TJ_440, "test_yuv1");
dotest(48, 48, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv0"); dotest(48, 48, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv0");
dotest(35, 39, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv1"); dotest(35, 39, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv1");
dotest(48, 48, _onlygray, 1, TJ_GRAYSCALE, "test_yuv0"); dotest(48, 48, _onlygray, 1, TJ_GRAYSCALE, "test_yuv0");

View File

@@ -41,8 +41,8 @@ const int _rindex[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1};
const int _gindex[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2}; const int _gindex[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3}; const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
const char *_pfname[]={"RGB", "RGBX", "BGR", "BGRX", "XBGR", "XRGB"}; const char *_pfname[]={"RGB", "RGBX", "BGR", "BGRX", "XBGR", "XRGB"};
const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"}; const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"};
const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"}; const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"};
tjscalingfactor *sf=NULL; int nsf=0; tjscalingfactor *sf=NULL; int nsf=0;
int xformop=TJXFORM_NONE, xformopt=0; int xformop=TJXFORM_NONE, xformopt=0;
double benchtime=5.0; double benchtime=5.0;

View File

@@ -22,14 +22,19 @@
#define DLLCALL #define DLLCALL
/* Subsampling */ /* Subsampling */
#define NUMSUBOPT 4 #define NUMSUBOPT 5
enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE}; enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE, TJ_440};
#define TJ_411 TJ_420 /* for backward compatibility with VirtualGL <= 2.1.x, #define TJ_411 TJ_420 /* for backward compatibility with VirtualGL <= 2.1.x,
TurboVNC <= 0.6, and TurboJPEG/IPP */ TurboVNC <= 0.6, and TurboJPEG/IPP */
static const int tjmcuw[NUMSUBOPT]={8, 16, 16, 8}; /* MCU block sizes:
static const int tjmcuh[NUMSUBOPT]={8, 8, 16, 8}; 8x8 for no subsampling or grayscale
16x8 for 4:2:2
8x16 for 4:4:0
16x16 for 4:2:0 */
static const int tjmcuw[NUMSUBOPT]={8, 16, 16, 8, 8};
static const int tjmcuh[NUMSUBOPT]={8, 8, 16, 8, 16};
/* Flags */ /* Flags */
#define TJ_BGR 1 #define TJ_BGR 1
@@ -55,7 +60,7 @@ static const int tjmcuh[NUMSUBOPT]={8, 8, 16, 8};
/* Turn off CPU auto-detection and force TurboJPEG to use SSE3 code /* Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
(64-bit IPP version only) */ (64-bit IPP version only) */
#define TJ_FASTUPSAMPLE 256 #define TJ_FASTUPSAMPLE 256
/* Use fast, inaccurate 4:2:2 and 4:2:0 YUV upsampling routines in the JPEG /* Use fast, inaccurate chrominance upsampling routines in the JPEG
decompressor (libjpeg and libjpeg-turbo versions only) */ decompressor (libjpeg and libjpeg-turbo versions only) */
#define TJ_YUV 512 #define TJ_YUV 512
/* Nothing to see here. Pay no attention to the man behind the curtain. */ /* Nothing to see here. Pay no attention to the man behind the curtain. */
@@ -96,11 +101,11 @@ TJXFORM_ROT270 /* Rotate image counter-clockwise by 90 degrees. This
#define TJXFORM_PERFECT 1 #define TJXFORM_PERFECT 1
/* This will cause the tjTransform() function to return an error if the /* This will cause the tjTransform() function to return an error if the
transform is not perfect. Lossless transforms operate on MCU blocks, transform is not perfect. Lossless transforms operate on MCU blocks,
which are 8x8 pixels if no chrominance subsampling is used, or 16x8 for whose size depends on the level of chrominance subsampling used (see
4:2:2 or 16x16 for 4:2:0. If the image's width or height is not evenly "MCU block sizes" above). If the image's width or height is not evenly
divisible by the MCU size, then there will be partial MCU blocks on the divisible by the MCU block size, then there will be partial MCU blocks on
right and/or bottom edges. It is not possible to move these partial MCU the right and/or bottom edges. It is not possible to move these partial
blocks to the top or left of the image, so any transform that would MCU blocks to the top or left of the image, so any transform that would
require that is "imperfect." If this option is not specified, then any require that is "imperfect." If this option is not specified, then any
partial MCU blocks that cannot be transformed will be left in place, which partial MCU blocks that cannot be transformed will be left in place, which
will create odd-looking strips on the right or bottom edge of the image. will create odd-looking strips on the right or bottom edge of the image.
@@ -177,17 +182,19 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void);
the maximum size for this buffer based on the image width and height. the maximum size for this buffer based on the image width and height.
[OUTPUT] size = pointer to unsigned long which receives the actual size (in [OUTPUT] size = pointer to unsigned long which receives the actual size (in
bytes) of the JPEG image bytes) of the JPEG image
[INPUT] jpegsubsamp = Specifies either 4:2:0, 4:2:2, 4:4:4, or grayscale [INPUT] jpegsubsamp = Specifies the level of chrominance subsampling. When
subsampling. When the image is converted from the RGB to YCbCr colorspace the image is converted from the RGB to YCbCr colorspace as part of the
as part of the JPEG compression process, every other Cb and Cr JPEG compression process, every other Cb and Cr (chrominance) pixel can be
(chrominance) pixel can be discarded to produce a smaller image with discarded to produce a smaller image with little perceptible loss of image
little perceptible loss of image clarity (the human eye is more sensitive clarity (the human eye is more sensitive to small changes in brightness
to small changes in brightness than small changes in color.) than small changes in color.)
TJ_420: 4:2:0 subsampling. Discards every other Cb, Cr pixel in both TJ_420: 4:2:0 subsampling. Discards every other Cb, Cr pixel in both
horizontal and vertical directions horizontal and vertical directions
TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in
the horizontal direction the horizontal direction
TJ_440: 4:4:0 subsampling. Discards every other Cb, Cr pixel only in
the vertical direction
TJ_444: no subsampling TJ_444: no subsampling
TJ_GRAYSCALE: Generate grayscale JPEG image TJ_GRAYSCALE: Generate grayscale JPEG image
@@ -262,8 +269,7 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
determine the appropriate size for this buffer based on the image width, determine the appropriate size for this buffer based on the image width,
height, and level of subsampling. height, and level of subsampling.
[INPUT] subsamp = specifies the level of chrominance subsampling for the [INPUT] subsamp = specifies the level of chrominance subsampling for the
YUV image (4:2:0, 4:2:2, 4:4:4, or grayscale.) See description under YUV image. See description under tjCompress())
tjCompress())
[INPUT] flags = the bitwise OR of one or more of the flags described in the [INPUT] flags = the bitwise OR of one or more of the flags described in the
"Flags" section above "Flags" section above
@@ -388,9 +394,8 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle hnd,
step, so a planar YUV image is generated instead of an RGB image. The step, so a planar YUV image is generated instead of an RGB image. The
padding of the planes in this image is the same as the images generated padding of the planes in this image is the same as the images generated
by tjEncodeYUV(). Note that, if the width or height of the image is not an by tjEncodeYUV(). Note that, if the width or height of the image is not an
even multiple of the MCU block size (8x8 if the JPEG image was compressed even multiple of the MCU block size (see "MCU block sizes" above), then an
using grayscale or no subsampling, or 16x8 for 4:2:2 or 16x16 for 4:2:0), intermediate buffer copy will be performed within TurboJPEG.
then an intermediate buffer copy will be performed within TurboJPEG.
[INPUT] hnd = instance handle previously returned from a call to [INPUT] hnd = instance handle previously returned from a call to
tjInitDecompress() or tjInitTransform() tjInitDecompress() or tjInitTransform()

View File

@@ -68,7 +68,7 @@ typedef struct _jpgstruct
int initc, initd; int initc, initd;
} jpgstruct; } jpgstruct;
static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1}; static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1, 3};
static const JXFORM_CODE xformtypes[NUMXFORMOPT]={ static const JXFORM_CODE xformtypes[NUMXFORMOPT]={
JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE, JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270 JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270