add LUT-free reference code for YUV->RGB conversion.
Reported to eventually be 4% on ARM (see https://code.google.com/p/webp/issues/detail?id=134 for details) We might activate it selectively later... Output values is not bitwise the same as the LUT-based version, but difference is only +/-1 at max. Change-Id: I1cc790ff4459885ed2ae2e72f31c5f3740095f07
This commit is contained in:
		| @@ -15,7 +15,7 @@ | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| enum { YUV_HALF = 1 << (YUV_FIX - 1) }; | ||||
| #ifdef WEBP_YUV_USE_TABLE | ||||
|  | ||||
| int16_t VP8kVToR[256], VP8kUToB[256]; | ||||
| int32_t VP8kVToG[256], VP8kUToG[256]; | ||||
| @@ -62,6 +62,12 @@ void VP8YUVInit(void) { | ||||
|   done = 1; | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| void VP8YUVInit(void) {} | ||||
|  | ||||
| #endif  // WEBP_YUV_USE_TABLE | ||||
|  | ||||
| #if defined(__cplusplus) || defined(c_plusplus) | ||||
| }    // extern "C" | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										119
									
								
								src/dsp/yuv.h
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								src/dsp/yuv.h
									
									
									
									
									
								
							| @@ -19,8 +19,9 @@ | ||||
| //   G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) | ||||
| //   B = 1.164 * (Y-16)                   + 2.018 * (U-128) | ||||
| // where Y is in the [16,235] range, and U/V in the [16,240] range. | ||||
| // But the common term 1.164 * (Y-16) can be handled as an offset in the | ||||
| // VP8kClip[] table. So the formulae should be read as: | ||||
| // In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor | ||||
| // "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table. | ||||
| // So in this case the formulae should be read as: | ||||
| //   R = 1.164 * [Y + 1.371 * (V-128)                  ] - 18.624 | ||||
| //   G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624 | ||||
| //   B = 1.164 * [Y                   + 1.733 * (U-128)] - 18.624 | ||||
| @@ -33,6 +34,9 @@ | ||||
|  | ||||
| #include "../dec/decode_vp8.h" | ||||
|  | ||||
| // Define the following to use the LUT-based code: | ||||
| #define WEBP_YUV_USE_TABLE | ||||
|  | ||||
| #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. | ||||
| @@ -51,9 +55,14 @@ extern "C" { | ||||
| #endif | ||||
|  | ||||
| enum { YUV_FIX = 16,                // fixed-point precision | ||||
|        YUV_HALF = 1 << (YUV_FIX - 1), | ||||
|        YUV_MASK = (256 << YUV_FIX) - 1, | ||||
|        YUV_RANGE_MIN = -227,        // min value of r/g/b output | ||||
|        YUV_RANGE_MAX = 256 + 226    // max value of r/g/b output | ||||
| }; | ||||
|  | ||||
| #ifdef WEBP_YUV_USE_TABLE | ||||
|  | ||||
| extern int16_t VP8kVToR[256], VP8kUToB[256]; | ||||
| extern int32_t VP8kVToG[256], VP8kUToG[256]; | ||||
| extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; | ||||
| @@ -69,6 +78,16 @@ static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, | ||||
|   rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                     uint8_t* const bgr) { | ||||
|   const int r_off = VP8kVToR[v]; | ||||
|   const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; | ||||
|   const int b_off = VP8kUToB[u]; | ||||
|   bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; | ||||
|   bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; | ||||
|   bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                        uint8_t* const rgb) { | ||||
|   const int r_off = VP8kVToR[v]; | ||||
| @@ -87,12 +106,6 @@ static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                      uint8_t* const argb) { | ||||
|   argb[0] = 0xff; | ||||
|   VP8YuvToRgb(y, u, v, argb + 1); | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                          uint8_t* const argb) { | ||||
|   const int r_off = VP8kVToR[v]; | ||||
| @@ -110,14 +123,92 @@ static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #else   // Table-free version (slower on x86) | ||||
|  | ||||
| // These constants are 16b fixed-point version of ITU-R BT.601 constants | ||||
| #define kYScale 76309      // 1.164 = 255 / 219 | ||||
| #define kVToR   104597     // 1.596 = 255 / 112 * 0.701 | ||||
| #define kUToG   25674      // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587 | ||||
| #define kVToG   53278      // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587 | ||||
| #define kUToB   132201     // 2.018 = 255 / 112 * 0.886 | ||||
| #define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF) | ||||
| #define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF) | ||||
| #define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF) | ||||
|  | ||||
| static WEBP_INLINE uint8_t VP8Clip8(int v) { | ||||
|   return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX) | ||||
|                                 : (v < 0) ? 0u : 255u; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE uint8_t VP8ClipN(int v, int N) {  // clip to N bits | ||||
|   return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N))) | ||||
|                                 : (v < 0) ? 0u : (255u >> (8 - N)); | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE int VP8YUVToR(int y, int v) { | ||||
|   return kYScale * y + kVToR * v + kRCst; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE int VP8YUVToG(int y, int u, int v) { | ||||
|   return kYScale * y - kUToG * u - kVToG * v + kGCst; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE int VP8YUVToB(int y, int u) { | ||||
|   return kYScale * y  + kUToB * u + kBCst; | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                     uint8_t* const rgb) { | ||||
|   rgb[0] = VP8Clip8(VP8YUVToR(y, v)); | ||||
|   rgb[1] = VP8Clip8(VP8YUVToG(y, u, v)); | ||||
|   rgb[2] = VP8Clip8(VP8YUVToB(y, u)); | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                     uint8_t* const bgr) { | ||||
|   const int r_off = VP8kVToR[v]; | ||||
|   const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; | ||||
|   const int b_off = VP8kUToB[u]; | ||||
|   bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; | ||||
|   bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; | ||||
|   bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; | ||||
|   bgr[0] = VP8Clip8(VP8YUVToB(y, u)); | ||||
|   bgr[1] = VP8Clip8(VP8YUVToG(y, u, v)); | ||||
|   bgr[2] = VP8Clip8(VP8YUVToR(y, v)); | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                        uint8_t* const rgb) { | ||||
|   const int r = VP8Clip8(VP8YUVToR(y, u)); | ||||
|   const int g = VP8ClipN(VP8YUVToG(y, u, v), 6); | ||||
|   const int b = VP8ClipN(VP8YUVToB(y, v), 5); | ||||
|   const uint8_t rg = (r & 0xf8) | (g >> 3); | ||||
|   const uint8_t gb = (g << 5) | b; | ||||
| #ifdef WEBP_SWAP_16BIT_CSP | ||||
|   rgb[0] = gb; | ||||
|   rgb[1] = rg; | ||||
| #else | ||||
|   rgb[0] = rg; | ||||
|   rgb[1] = gb; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                          uint8_t* const argb) { | ||||
|   const int r = VP8Clip8(VP8YUVToR(y, u)); | ||||
|   const int g = VP8ClipN(VP8YUVToG(y, u, v), 4); | ||||
|   const int b = VP8Clip8(VP8YUVToB(y, v)); | ||||
|   const uint8_t rg = (r & 0xf0) | g; | ||||
|   const uint8_t ba = b | 0x0f;   // overwrite the lower 4 bits | ||||
| #ifdef WEBP_SWAP_16BIT_CSP | ||||
|   argb[0] = ba; | ||||
|   argb[1] = rg; | ||||
| #else | ||||
|   argb[0] = rg; | ||||
|   argb[1] = ba; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #endif  // WEBP_YUV_USE_TABLE | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, | ||||
|                                      uint8_t* const argb) { | ||||
|   argb[0] = 0xff; | ||||
|   VP8YuvToRgb(y, u, v, argb + 1); | ||||
| } | ||||
|  | ||||
| static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 skal
					skal