OLD | NEW |
1 // Copyright 2011 Google Inc. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // This code is licensed under the same terms as WebM: |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // Software License Agreement: http://www.webmproject.org/license/software/ |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ |
6 // ----------------------------------------------------------------------------- | 6 // ----------------------------------------------------------------------------- |
7 // | 7 // |
8 // YUV to RGB upsampling functions. | 8 // YUV to RGB upsampling functions. |
9 // | 9 // |
10 // Author: somnath@google.com (Somnath Banerjee) | 10 // Author: somnath@google.com (Somnath Banerjee) |
11 | 11 |
12 #include "./dsp.h" | 12 #include "./dsp.h" |
13 #include "./yuv.h" | 13 #include "./yuv.h" |
14 #include "../dec/webpi.h" | |
15 | 14 |
16 #if defined(__cplusplus) || defined(c_plusplus) | 15 #if defined(__cplusplus) || defined(c_plusplus) |
17 extern "C" { | 16 extern "C" { |
18 #endif | 17 #endif |
19 | 18 |
20 //------------------------------------------------------------------------------ | 19 //------------------------------------------------------------------------------ |
21 // Fancy upsampler | 20 // Fancy upsampler |
22 | 21 |
23 #ifdef FANCY_UPSAMPLING | 22 #ifdef FANCY_UPSAMPLING |
24 | 23 |
25 // Fancy upsampling functions to convert YUV to RGB | 24 // Fancy upsampling functions to convert YUV to RGB |
26 WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; | 25 WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; |
27 WebPUpsampleLinePairFunc WebPUpsamplersKeepAlpha[MODE_LAST]; | |
28 | 26 |
29 // Given samples laid out in a square as: | 27 // Given samples laid out in a square as: |
30 // [a b] | 28 // [a b] |
31 // [c d] | 29 // [c d] |
32 // we interpolate u/v as: | 30 // we interpolate u/v as: |
33 // ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 | 31 // ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 |
34 // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 | 32 // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 |
35 | 33 |
36 // We process u and v together stashed into 32bit (16bit each). | 34 // We process u and v together stashed into 32bit (16bit each). |
37 #define LOAD_UV(u,v) ((u) | ((v) << 16)) | 35 #define LOAD_UV(u,v) ((u) | ((v) << 16)) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 } | 92 } |
95 | 93 |
96 // All variants implemented. | 94 // All variants implemented. |
97 UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) | 95 UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) |
98 UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) | 96 UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) |
99 UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) | 97 UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) |
100 UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) | 98 UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) |
101 UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) | 99 UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) |
102 UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) | 100 UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) |
103 UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) | 101 UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) |
104 // These two don't erase the alpha value | |
105 UPSAMPLE_FUNC(UpsampleRgbKeepAlphaLinePair, VP8YuvToRgb, 4) | |
106 UPSAMPLE_FUNC(UpsampleBgrKeepAlphaLinePair, VP8YuvToBgr, 4) | |
107 UPSAMPLE_FUNC(UpsampleArgbKeepAlphaLinePair, VP8YuvToArgbKeepA, 4) | |
108 UPSAMPLE_FUNC(UpsampleRgba4444KeepAlphaLinePair, VP8YuvToRgba4444KeepA, 2) | |
109 | 102 |
110 #undef LOAD_UV | 103 #undef LOAD_UV |
111 #undef UPSAMPLE_FUNC | 104 #undef UPSAMPLE_FUNC |
112 | 105 |
113 #endif // FANCY_UPSAMPLING | 106 #endif // FANCY_UPSAMPLING |
114 | 107 |
115 //------------------------------------------------------------------------------ | 108 //------------------------------------------------------------------------------ |
116 // simple point-sampling | 109 // simple point-sampling |
117 | 110 |
118 #define SAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ | 111 #define SAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ |
(...skipping 30 matching lines...) Expand all Loading... |
149 | 142 |
150 #undef SAMPLE_FUNC | 143 #undef SAMPLE_FUNC |
151 | 144 |
152 const WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = { | 145 const WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = { |
153 SampleRgbLinePair, // MODE_RGB | 146 SampleRgbLinePair, // MODE_RGB |
154 SampleRgbaLinePair, // MODE_RGBA | 147 SampleRgbaLinePair, // MODE_RGBA |
155 SampleBgrLinePair, // MODE_BGR | 148 SampleBgrLinePair, // MODE_BGR |
156 SampleBgraLinePair, // MODE_BGRA | 149 SampleBgraLinePair, // MODE_BGRA |
157 SampleArgbLinePair, // MODE_ARGB | 150 SampleArgbLinePair, // MODE_ARGB |
158 SampleRgba4444LinePair, // MODE_RGBA_4444 | 151 SampleRgba4444LinePair, // MODE_RGBA_4444 |
159 SampleRgb565LinePair // MODE_RGB_565 | 152 SampleRgb565LinePair, // MODE_RGB_565 |
| 153 SampleRgbaLinePair, // MODE_rgbA |
| 154 SampleBgraLinePair, // MODE_bgrA |
| 155 SampleArgbLinePair, // MODE_Argb |
| 156 SampleRgba4444LinePair // MODE_rgbA_4444 |
160 }; | 157 }; |
161 | 158 |
162 //------------------------------------------------------------------------------ | 159 //------------------------------------------------------------------------------ |
| 160 |
| 161 #if !defined(FANCY_UPSAMPLING) |
| 162 #define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ |
| 163 static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ |
| 164 const uint8_t* top_u, const uint8_t* top_v, \ |
| 165 const uint8_t* bot_u, const uint8_t* bot_v, \ |
| 166 uint8_t* top_dst, uint8_t* bot_dst, int len) { \ |
| 167 const int half_len = len >> 1; \ |
| 168 int x; \ |
| 169 if (top_dst != NULL) { \ |
| 170 for (x = 0; x < half_len; ++x) { \ |
| 171 FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ |
| 172 FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ |
| 173 } \ |
| 174 if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ |
| 175 } \ |
| 176 if (bot_dst != NULL) { \ |
| 177 for (x = 0; x < half_len; ++x) { \ |
| 178 FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ |
| 179 FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ |
| 180 } \ |
| 181 if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ |
| 182 } \ |
| 183 } |
| 184 |
| 185 DUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) |
| 186 DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) |
| 187 #undef DUAL_SAMPLE_FUNC |
| 188 |
| 189 #endif // !FANCY_UPSAMPLING |
| 190 |
| 191 WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { |
| 192 WebPInitUpsamplers(); |
| 193 VP8YUVInit(); |
| 194 #ifdef FANCY_UPSAMPLING |
| 195 return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; |
| 196 #else |
| 197 return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); |
| 198 #endif |
| 199 } |
| 200 |
| 201 //------------------------------------------------------------------------------ |
163 // YUV444 converter | 202 // YUV444 converter |
164 | 203 |
165 #define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ | 204 #define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ |
166 static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ | 205 static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ |
167 uint8_t* dst, int len) { \ | 206 uint8_t* dst, int len) { \ |
168 int i; \ | 207 int i; \ |
169 for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ | 208 for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ |
170 } | 209 } |
171 | 210 |
172 YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3) | 211 YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3) |
173 YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3) | 212 YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3) |
174 YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4) | 213 YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4) |
175 YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4) | 214 YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4) |
176 YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4) | 215 YUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4) |
177 YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2) | 216 YUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2) |
178 YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2) | 217 YUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2) |
179 | 218 |
180 #undef YUV444_FUNC | 219 #undef YUV444_FUNC |
181 | 220 |
182 const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { | 221 const WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { |
183 Yuv444ToRgb, // MODE_RGB | 222 Yuv444ToRgb, // MODE_RGB |
184 Yuv444ToRgba, // MODE_RGBA | 223 Yuv444ToRgba, // MODE_RGBA |
185 Yuv444ToBgr, // MODE_BGR | 224 Yuv444ToBgr, // MODE_BGR |
186 Yuv444ToBgra, // MODE_BGRA | 225 Yuv444ToBgra, // MODE_BGRA |
187 Yuv444ToArgb, // MODE_ARGB | 226 Yuv444ToArgb, // MODE_ARGB |
188 Yuv444ToRgba4444, // MODE_RGBA_4444 | 227 Yuv444ToRgba4444, // MODE_RGBA_4444 |
189 Yuv444ToRgb565 // MODE_RGB_565 | 228 Yuv444ToRgb565, // MODE_RGB_565 |
| 229 Yuv444ToRgba, // MODE_rgbA |
| 230 Yuv444ToBgra, // MODE_bgrA |
| 231 Yuv444ToArgb, // MODE_Argb |
| 232 Yuv444ToRgba4444 // MODE_rgbA_4444 |
190 }; | 233 }; |
191 | 234 |
192 //------------------------------------------------------------------------------ | 235 //------------------------------------------------------------------------------ |
| 236 // Premultiplied modes |
| 237 |
| 238 // non dithered-modes |
| 239 |
| 240 // (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) |
| 241 // for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), |
| 242 // one can use instead: (x * a * 65793 + (1 << 23)) >> 24 |
| 243 #if 1 // (int)(x * a / 255.) |
| 244 #define MULTIPLIER(a) ((a) * 32897UL) |
| 245 #define PREMULTIPLY(x, m) (((x) * (m)) >> 23) |
| 246 #else // (int)(x * a / 255. + .5) |
| 247 #define MULTIPLIER(a) ((a) * 65793UL) |
| 248 #define PREMULTIPLY(x, m) (((x) * (m) + (1UL << 23)) >> 24) |
| 249 #endif |
| 250 |
| 251 static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, |
| 252 int w, int h, int stride) { |
| 253 while (h-- > 0) { |
| 254 uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); |
| 255 const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); |
| 256 int i; |
| 257 for (i = 0; i < w; ++i) { |
| 258 const uint32_t a = alpha[4 * i]; |
| 259 if (a != 0xff) { |
| 260 const uint32_t mult = MULTIPLIER(a); |
| 261 rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); |
| 262 rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); |
| 263 rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); |
| 264 } |
| 265 } |
| 266 rgba += stride; |
| 267 } |
| 268 } |
| 269 #undef MULTIPLIER |
| 270 #undef PREMULTIPLY |
| 271 |
| 272 // rgbA4444 |
| 273 |
| 274 #define MULTIPLIER(a) ((a) * 0x11) |
| 275 #define PREMULTIPLY(x, m) (((x) * (m)) >> 12) |
| 276 |
| 277 static WEBP_INLINE uint8_t dither_hi(uint8_t x) { |
| 278 return (x & 0xf0) | (x >> 4); |
| 279 } |
| 280 |
| 281 static WEBP_INLINE uint8_t dither_lo(uint8_t x) { |
| 282 return (x & 0x0f) | (x << 4); |
| 283 } |
| 284 |
| 285 static void ApplyAlphaMultiply4444(uint8_t* rgba4444, |
| 286 int w, int h, int stride) { |
| 287 while (h-- > 0) { |
| 288 int i; |
| 289 for (i = 0; i < w; ++i) { |
| 290 const uint8_t a = dither_lo(rgba4444[2 * i + 1]); |
| 291 const uint32_t mult = MULTIPLIER(a); |
| 292 const uint8_t r = PREMULTIPLY(dither_hi(rgba4444[2 * i + 0]), mult); |
| 293 const uint8_t g = PREMULTIPLY(dither_lo(rgba4444[2 * i + 0]), mult); |
| 294 const uint8_t b = PREMULTIPLY(dither_hi(rgba4444[2 * i + 1]), mult); |
| 295 rgba4444[2 * i + 0] = (r & 0xf0) | (g & 0x0f); |
| 296 rgba4444[2 * i + 1] = (b & 0xf0) | a; |
| 297 } |
| 298 rgba4444 += stride; |
| 299 } |
| 300 } |
| 301 #undef MULTIPLIER |
| 302 #undef PREMULTIPLY |
| 303 |
| 304 void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int) |
| 305 = ApplyAlphaMultiply; |
| 306 void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int) |
| 307 = ApplyAlphaMultiply4444; |
| 308 |
| 309 //------------------------------------------------------------------------------ |
193 // Main call | 310 // Main call |
194 | 311 |
195 void WebPInitUpsamplers(void) { | 312 void WebPInitUpsamplers(void) { |
196 #ifdef FANCY_UPSAMPLING | 313 #ifdef FANCY_UPSAMPLING |
197 WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; | 314 WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; |
198 WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; | 315 WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; |
199 WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; | 316 WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; |
200 WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; | 317 WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; |
201 WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; | 318 WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; |
202 WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; | 319 WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; |
203 WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; | 320 WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; |
204 | 321 |
205 WebPUpsamplersKeepAlpha[MODE_RGB] = UpsampleRgbLinePair; | |
206 WebPUpsamplersKeepAlpha[MODE_RGBA] = UpsampleRgbKeepAlphaLinePair; | |
207 WebPUpsamplersKeepAlpha[MODE_BGR] = UpsampleBgrLinePair; | |
208 WebPUpsamplersKeepAlpha[MODE_BGRA] = UpsampleBgrKeepAlphaLinePair; | |
209 WebPUpsamplersKeepAlpha[MODE_ARGB] = UpsampleArgbKeepAlphaLinePair; | |
210 WebPUpsamplersKeepAlpha[MODE_RGBA_4444] = UpsampleRgba4444KeepAlphaLinePair; | |
211 WebPUpsamplersKeepAlpha[MODE_RGB_565] = UpsampleRgb565LinePair; | |
212 | |
213 // If defined, use CPUInfo() to overwrite some pointers with faster versions. | 322 // If defined, use CPUInfo() to overwrite some pointers with faster versions. |
214 if (VP8GetCPUInfo) { | 323 if (VP8GetCPUInfo != NULL) { |
215 #if defined(__SSE2__) || defined(_MSC_VER) | 324 #if defined(WEBP_USE_SSE2) |
216 if (VP8GetCPUInfo(kSSE2)) { | 325 if (VP8GetCPUInfo(kSSE2)) { |
217 WebPInitUpsamplersSSE2(); | 326 WebPInitUpsamplersSSE2(); |
218 } | 327 } |
219 #endif | 328 #endif |
220 } | 329 } |
221 #endif // FANCY_UPSAMPLING | 330 #endif // FANCY_UPSAMPLING |
222 } | 331 } |
223 | 332 |
| 333 void WebPInitPremultiply(void) { |
| 334 WebPApplyAlphaMultiply = ApplyAlphaMultiply; |
| 335 WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply4444; |
| 336 |
| 337 #ifdef FANCY_UPSAMPLING |
| 338 WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; |
| 339 WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; |
| 340 WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; |
| 341 WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; |
| 342 |
| 343 if (VP8GetCPUInfo != NULL) { |
| 344 #if defined(WEBP_USE_SSE2) |
| 345 if (VP8GetCPUInfo(kSSE2)) { |
| 346 WebPInitPremultiplySSE2(); |
| 347 } |
| 348 #endif |
| 349 } |
| 350 #endif // FANCY_UPSAMPLING |
| 351 } |
| 352 |
224 #if defined(__cplusplus) || defined(c_plusplus) | 353 #if defined(__cplusplus) || defined(c_plusplus) |
225 } // extern "C" | 354 } // extern "C" |
226 #endif | 355 #endif |
OLD | NEW |