Home | History | Annotate | Download | only in dec
      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