| 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 |