Vikas Arora | a241572 | 2012-08-09 16:18:58 -0700 | [diff] [blame] | 1 | // Copyright 2010 Google Inc. All Rights Reserved. |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 2 | // |
Vikas Arora | 0406ce1 | 2013-08-09 15:57:12 -0700 | [diff] [blame] | 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. |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 8 | // ----------------------------------------------------------------------------- |
| 9 | // |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 10 | // YUV->RGB conversion functions |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 11 | // |
| 12 | // Author: Skal (pascal.massimino@gmail.com) |
| 13 | |
Vikas Arora | a241572 | 2012-08-09 16:18:58 -0700 | [diff] [blame] | 14 | #include "./yuv.h" |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 15 | |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 16 | #if defined(WEBP_YUV_USE_TABLE) |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 17 | |
| 18 | static int done = 0; |
| 19 | |
Vikas Arora | a241572 | 2012-08-09 16:18:58 -0700 | [diff] [blame] | 20 | static WEBP_INLINE uint8_t clip(int v, int max_value) { |
Vikas Arora | 4667279 | 2011-07-13 16:37:55 +0530 | [diff] [blame] | 21 | return v < 0 ? 0 : v > max_value ? max_value : v; |
| 22 | } |
| 23 | |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 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 | |
Vikas Arora | 03d5e34 | 2011-06-02 23:59:44 +0530 | [diff] [blame] | 29 | void VP8YUVInit(void) { |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 30 | int i; |
| 31 | if (done) { |
| 32 | return; |
| 33 | } |
Vikas Arora | 1e7bf88 | 2013-03-13 16:43:18 -0700 | [diff] [blame] | 34 | #ifndef USE_YUVj |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 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; |
Vikas Arora | 4667279 | 2011-07-13 16:37:55 +0530 | [diff] [blame] | 43 | VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); |
| 44 | VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 45 | } |
Vikas Arora | 1e7bf88 | 2013-03-13 16:43:18 -0700 | [diff] [blame] | 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 | |
Eric Hassold | 9aea642 | 2011-01-04 17:22:46 -0800 | [diff] [blame] | 60 | done = 1; |
| 61 | } |
| 62 | |
Vikas Arora | 0406ce1 | 2013-08-09 15:57:12 -0700 | [diff] [blame] | 63 | #else |
| 64 | |
| 65 | void VP8YUVInit(void) {} |
| 66 | |
| 67 | #endif // WEBP_YUV_USE_TABLE |
| 68 | |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 69 | //----------------------------------------------------------------------------- |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 70 | // Plain-C version |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 71 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 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 | } \ |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 89 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 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) |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 98 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 99 | #undef ROW_FUNC |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 100 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 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; |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 113 | } |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 114 | dst += dst_stride; |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 115 | } |
| 116 | } |
| 117 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 118 | //----------------------------------------------------------------------------- |
| 119 | // Main call |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 120 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 121 | WebPSamplerRowFunc WebPSamplers[MODE_LAST]; |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 122 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 123 | extern void WebPInitSamplersSSE2(void); |
| 124 | extern void WebPInitSamplersMIPS32(void); |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 125 | |
James Zern | 9e80ee9 | 2015-03-17 18:54:21 -0700 | [diff] [blame] | 126 | static volatile VP8CPUInfo yuv_last_cpuinfo_used = |
| 127 | (VP8CPUInfo)&yuv_last_cpuinfo_used; |
| 128 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 129 | void WebPInitSamplers(void) { |
James Zern | 9e80ee9 | 2015-03-17 18:54:21 -0700 | [diff] [blame] | 130 | if (yuv_last_cpuinfo_used == VP8GetCPUInfo) return; |
| 131 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 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; |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 143 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 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 | } |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 150 | #endif // WEBP_USE_SSE2 |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 151 | #if defined(WEBP_USE_MIPS32) |
| 152 | if (VP8GetCPUInfo(kMIPS32)) { |
| 153 | WebPInitSamplersMIPS32(); |
| 154 | } |
| 155 | #endif // WEBP_USE_MIPS32 |
| 156 | } |
James Zern | 9e80ee9 | 2015-03-17 18:54:21 -0700 | [diff] [blame] | 157 | yuv_last_cpuinfo_used = VP8GetCPUInfo; |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 158 | } |
Vikas Arora | 8b72022 | 2014-01-02 16:48:02 -0800 | [diff] [blame] | 159 | |
Vikas Arora | 33f74da | 2014-07-25 13:53:32 -0700 | [diff] [blame] | 160 | //----------------------------------------------------------------------------- |