add EXPERIMENTAL code for YUV-JPEG colorspace

This is mostly for experimentation!
Need to define USE_YUVj flag in the code for that.

suggested by benwreder at hotmail dot com

Change-Id: If0b8e2c1863efc08ce097de6de20f4c7efc3f7e8
This commit is contained in:
skal 2012-10-18 14:55:39 +02:00
parent c3aa215afa
commit f0360b4fcf
2 changed files with 61 additions and 8 deletions

View File

@ -33,6 +33,7 @@ void VP8YUVInit(void) {
if (done) { if (done) {
return; return;
} }
#ifndef USE_YUVj
for (i = 0; i < 256; ++i) { for (i = 0; i < 256; ++i) {
VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
@ -44,6 +45,20 @@ void VP8YUVInit(void) {
VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
} }
#else
for (i = 0; i < 256; ++i) {
VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX;
VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF;
VP8kVToG[i] = -46802 * (i - 128);
VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX;
}
for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
const int k = i;
VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
}
#endif
done = 1; done = 1;
} }

View File

@ -7,6 +7,13 @@
// //
// inline YUV<->RGB conversion function // inline YUV<->RGB conversion function
// //
// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
// More information at: http://en.wikipedia.org/wiki/YCbCr
// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
// We use 16bit fixed point operations for RGB->YUV conversion.
//
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_DSP_YUV_H_ #ifndef WEBP_DSP_YUV_H_
@ -14,6 +21,16 @@
#include "../dec/decode_vp8.h" #include "../dec/decode_vp8.h"
#if defined(WEBP_EXPERIMENTAL_FEATURES)
// Do NOT activate this feature for real compression. This is only experimental!
// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
// This colorspace is close to Rec.601's Y'CbCr model with the notable
// difference of allowing larger range for luma/chroma.
// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its
// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
// #define USE_YUVj
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// YUV -> RGB conversion // YUV -> RGB conversion
@ -95,18 +112,14 @@ void VP8YUVInit(void);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// RGB -> YUV conversion // RGB -> YUV conversion
// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
// More information at: http://en.wikipedia.org/wiki/YCbCr
// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
// We use 16bit fixed point operations.
static WEBP_INLINE int VP8ClipUV(int v) { static WEBP_INLINE int VP8ClipUV(int v) {
v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2);
return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255;
} }
#ifndef USE_YUVj
static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX); const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX);
const int luma = 16839 * r + 33059 * g + 6420 * b; const int luma = 16839 * r + 33059 * g + 6420 * b;
@ -114,13 +127,38 @@ static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
} }
static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
return VP8ClipUV(-9719 * r - 19081 * g + 28800 * b); const int u = -9719 * r - 19081 * g + 28800 * b;
return VP8ClipUV(u);
} }
static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
return VP8ClipUV(+28800 * r - 24116 * g - 4684 * b); const int v = +28800 * r - 24116 * g - 4684 * b;
return VP8ClipUV(v);
} }
#else
// This JPEG-YUV colorspace, only for comparison!
// These are also 16-bit precision coefficients from Rec.601, but with full
// [0..255] output range.
static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
const int kRound = (1 << (YUV_FIX - 1));
const int luma = 19595 * r + 38470 * g + 7471 * b;
return (luma + kRound) >> YUV_FIX; // no need to clip
}
static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
const int u = -11058 * r - 21710 * g + 32768 * b;
return VP8ClipUV(u);
}
static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
const int v = 32768 * r - 27439 * g - 5329 * b;
return VP8ClipUV(v);
}
#endif // USE_YUVj
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
} // extern "C" } // extern "C"
#endif #endif