Home | History | Annotate | Download | only in dsp
      1 // Copyright 2010 Google Inc. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the COPYING file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS. All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 // -----------------------------------------------------------------------------
      9 //
     10 // YUV->RGB conversion functions
     11 //
     12 // Author: Skal (pascal.massimino (at) gmail.com)
     13 
     14 #include "./yuv.h"
     15 
     16 #if defined(WEBP_YUV_USE_TABLE)
     17 
     18 static int done = 0;
     19 
     20 static WEBP_INLINE uint8_t clip(int v, int max_value) {
     21   return v < 0 ? 0 : v > max_value ? max_value : v;
     22 }
     23 
     24 int16_t VP8kVToR[256], VP8kUToB[256];
     25 int32_t VP8kVToG[256], VP8kUToG[256];
     26 uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
     27 uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
     28 
     29 void VP8YUVInit(void) {
     30   int i;
     31   if (done) {
     32     return;
     33   }
     34 #ifndef USE_YUVj
     35   for (i = 0; i < 256; ++i) {
     36     VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX;
     37     VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF;
     38     VP8kVToG[i] = -45773 * (i - 128);
     39     VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX;
     40   }
     41   for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
     42     const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX;
     43     VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
     44     VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
     45   }
     46 #else
     47   for (i = 0; i < 256; ++i) {
     48     VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX;
     49     VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF;
     50     VP8kVToG[i] = -46802 * (i - 128);
     51     VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX;
     52   }
     53   for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) {
     54     const int k = i;
     55     VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255);
     56     VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15);
     57   }
     58 #endif
     59 
     60   done = 1;
     61 }
     62 
     63 #else
     64 
     65 void VP8YUVInit(void) {}
     66 
     67 #endif  // WEBP_YUV_USE_TABLE
     68 
     69 //-----------------------------------------------------------------------------
     70 // Plain-C version
     71 
     72 #define ROW_FUNC(FUNC_NAME, FUNC, XSTEP)                                       \
     73 static void FUNC_NAME(const uint8_t* y,                                        \
     74                       const uint8_t* u, const uint8_t* v,                      \
     75                       uint8_t* dst, int len) {                                 \
     76   const uint8_t* const end = dst + (len & ~1) * XSTEP;                         \
     77   while (dst != end) {                                                         \
     78     FUNC(y[0], u[0], v[0], dst);                                               \
     79     FUNC(y[1], u[0], v[0], dst + XSTEP);                                       \
     80     y += 2;                                                                    \
     81     ++u;                                                                       \
     82     ++v;                                                                       \
     83     dst += 2 * XSTEP;                                                          \
     84   }                                                                            \
     85   if (len & 1) {                                                               \
     86     FUNC(y[0], u[0], v[0], dst);                                               \
     87   }                                                                            \
     88 }                                                                              \
     89 
     90 // All variants implemented.
     91 ROW_FUNC(YuvToRgbRow,      VP8YuvToRgb,  3)
     92 ROW_FUNC(YuvToBgrRow,      VP8YuvToBgr,  3)
     93 ROW_FUNC(YuvToRgbaRow,     VP8YuvToRgba, 4)
     94 ROW_FUNC(YuvToBgraRow,     VP8YuvToBgra, 4)
     95 ROW_FUNC(YuvToArgbRow,     VP8YuvToArgb, 4)
     96 ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2)
     97 ROW_FUNC(YuvToRgb565Row,   VP8YuvToRgb565, 2)
     98 
     99 #undef ROW_FUNC
    100 
    101 // Main call for processing a plane with a WebPSamplerRowFunc function:
    102 void WebPSamplerProcessPlane(const uint8_t* y, int y_stride,
    103                              const uint8_t* u, const uint8_t* v, int uv_stride,
    104                              uint8_t* dst, int dst_stride,
    105                              int width, int height, WebPSamplerRowFunc func) {
    106   int j;
    107   for (j = 0; j < height; ++j) {
    108     func(y, u, v, dst, width);
    109     y += y_stride;
    110     if (j & 1) {
    111       u += uv_stride;
    112       v += uv_stride;
    113     }
    114     dst += dst_stride;
    115   }
    116 }
    117 
    118 //-----------------------------------------------------------------------------
    119 // Main call
    120 
    121 WebPSamplerRowFunc WebPSamplers[MODE_LAST];
    122 
    123 extern void WebPInitSamplersSSE2(void);
    124 extern void WebPInitSamplersMIPS32(void);
    125 
    126 static volatile VP8CPUInfo yuv_last_cpuinfo_used =
    127     (VP8CPUInfo)&yuv_last_cpuinfo_used;
    128 
    129 void WebPInitSamplers(void) {
    130   if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
    131 
    132   WebPSamplers[MODE_RGB]       = YuvToRgbRow;
    133   WebPSamplers[MODE_RGBA]      = YuvToRgbaRow;
    134   WebPSamplers[MODE_BGR]       = YuvToBgrRow;
    135   WebPSamplers[MODE_BGRA]      = YuvToBgraRow;
    136   WebPSamplers[MODE_ARGB]      = YuvToArgbRow;
    137   WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row;
    138   WebPSamplers[MODE_RGB_565]   = YuvToRgb565Row;
    139   WebPSamplers[MODE_rgbA]      = YuvToRgbaRow;
    140   WebPSamplers[MODE_bgrA]      = YuvToBgraRow;
    141   WebPSamplers[MODE_Argb]      = YuvToArgbRow;
    142   WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row;
    143 
    144   // If defined, use CPUInfo() to overwrite some pointers with faster versions.
    145   if (VP8GetCPUInfo != NULL) {
    146 #if defined(WEBP_USE_SSE2)
    147     if (VP8GetCPUInfo(kSSE2)) {
    148       WebPInitSamplersSSE2();
    149     }
    150 #endif  // WEBP_USE_SSE2
    151 #if defined(WEBP_USE_MIPS32)
    152     if (VP8GetCPUInfo(kMIPS32)) {
    153       WebPInitSamplersMIPS32();
    154     }
    155 #endif  // WEBP_USE_MIPS32
    156   }
    157   yuv_last_cpuinfo_used = VP8GetCPUInfo;
    158 }
    159 
    160 //-----------------------------------------------------------------------------
    161