1 // Copyright 2010 Google Inc. 2 // 3 // This code is licensed under the same terms as WebM: 4 // Software License Agreement: http://www.webmproject.org/license/software/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 6 // ----------------------------------------------------------------------------- 7 // 8 // inline YUV->RGB conversion function 9 // 10 // Author: Skal (pascal.massimino (at) gmail.com) 11 12 #ifndef WEBP_DEC_YUV_H_ 13 #define WEBP_DEC_YUV_H_ 14 15 #include "webp/decode_vp8.h" 16 17 /* 18 * Define ANDROID_WEBP_RGB to enable specific optimizations for Android 19 * RGBA_4444 & RGB_565 color support. 20 * 21 */ 22 23 #define ANDROID_WEBP_RGB 24 25 #if defined(__cplusplus) || defined(c_plusplus) 26 extern "C" { 27 #endif 28 29 enum { YUV_FIX = 16, // fixed-point precision 30 YUV_RANGE_MIN = -227, // min value of r/g/b output 31 YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output 32 }; 33 extern int16_t VP8kVToR[256], VP8kUToB[256]; 34 extern int32_t VP8kVToG[256], VP8kUToG[256]; 35 extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 36 extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 37 38 static inline void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, 39 uint8_t* const rgb) { 40 const int r_off = VP8kVToR[v]; 41 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 42 const int b_off = VP8kUToB[u]; 43 rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 44 rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 45 rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 46 } 47 48 static inline void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, 49 uint8_t* const rgb) { 50 const int r_off = VP8kVToR[v]; 51 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 52 const int b_off = VP8kUToB[u]; 53 #ifdef ANDROID_WEBP_RGB 54 rgb[1] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | 55 (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); 56 rgb[0] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | 57 (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); 58 #else 59 rgb[0] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | 60 (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); 61 rgb[1] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | 62 (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); 63 #endif 64 } 65 66 static inline void VP8YuvToArgbKeepA(uint8_t y, uint8_t u, uint8_t v, 67 uint8_t* const argb) { 68 // Don't update Aplha (argb[0]) 69 VP8YuvToRgb(y, u, v, argb + 1); 70 } 71 72 static inline void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, 73 uint8_t* const argb) { 74 argb[0] = 0xff; 75 VP8YuvToArgbKeepA(y, u, v, argb); 76 } 77 78 static inline void VP8YuvToRgba4444KeepA(uint8_t y, uint8_t u, uint8_t v, 79 uint8_t* const argb) { 80 const int r_off = VP8kVToR[v]; 81 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 82 const int b_off = VP8kUToB[u]; 83 #ifdef ANDROID_WEBP_RGB 84 argb[1] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | 85 VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); 86 argb[0] = (argb[0] & 0x0f) | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4); 87 #else 88 argb[0] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | 89 VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); 90 argb[1] = (argb[1] & 0x0f) | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4); 91 #endif 92 } 93 94 static inline void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, 95 uint8_t* const argb) { 96 #ifdef ANDROID_WEBP_RGB 97 argb[0] = 0x0f; 98 #else 99 argb[1] = 0x0f; 100 #endif 101 VP8YuvToRgba4444KeepA(y, u, v, argb); 102 } 103 104 static inline void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, 105 uint8_t* const bgr) { 106 const int r_off = VP8kVToR[v]; 107 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 108 const int b_off = VP8kUToB[u]; 109 bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 110 bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 111 bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 112 } 113 114 static inline void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, 115 uint8_t* const bgra) { 116 VP8YuvToBgr(y, u, v, bgra); 117 bgra[3] = 0xff; 118 } 119 120 static inline void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, 121 uint8_t* const rgba) { 122 VP8YuvToRgb(y, u, v, rgba); 123 rgba[3] = 0xff; 124 } 125 126 // Must be called before everything, to initialize the tables. 127 void VP8YUVInit(void); 128 129 #if defined(__cplusplus) || defined(c_plusplus) 130 } // extern "C" 131 #endif 132 133 #endif // WEBP_DEC_YUV_H_ 134