15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2010 Google Inc. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------- 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// YUV->RGB conversion functions 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./yuv.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(WEBP_YUV_USE_TABLE) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int done = 0; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE uint8_t clip(int v, int max_value) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return v < 0 ? 0 : v > max_value ? max_value : v; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int16_t VP8kVToR[256], VP8kUToB[256]; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int32_t VP8kVToG[256], VP8kUToG[256]; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8YUVInit(void) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (done) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef USE_YUVj 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < 256; ++i) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kVToG[i] = -45773 * (i - 128); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = 0; i < 256; ++i) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kVToG[i] = -46802 * (i - 128); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int k = i; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done = 1; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VP8YUVInit(void) {} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // WEBP_YUV_USE_TABLE 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//----------------------------------------------------------------------------- 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Plain-C version 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define ROW_FUNC(FUNC_NAME, FUNC, XSTEP) \ 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void FUNC_NAME(const uint8_t* y, \ 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const uint8_t* u, const uint8_t* v, \ 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* dst, int len) { \ 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const uint8_t* const end = dst + (len & ~1) * XSTEP; \ 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (dst != end) { \ 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FUNC(y[0], u[0], v[0], dst); \ 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FUNC(y[1], u[0], v[0], dst + XSTEP); \ 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) y += 2; \ 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++u; \ 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++v; \ 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dst += 2 * XSTEP; \ 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } \ 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (len & 1) { \ 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FUNC(y[0], u[0], v[0], dst); \ 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } \ 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} \ 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// All variants implemented. 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToRgbRow, VP8YuvToRgb, 3) 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToBgrRow, VP8YuvToBgr, 3) 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToRgbaRow, VP8YuvToRgba, 4) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToBgraRow, VP8YuvToBgra, 4) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToArgbRow, VP8YuvToArgb, 4) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToRgba4444Row, VP8YuvToRgba4444, 2) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ROW_FUNC(YuvToRgb565Row, VP8YuvToRgb565, 2) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#undef ROW_FUNC 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Main call for processing a plane with a WebPSamplerRowFunc function: 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebPSamplerProcessPlane(const uint8_t* y, int y_stride, 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const uint8_t* u, const uint8_t* v, int uv_stride, 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* dst, int dst_stride, 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int width, int height, WebPSamplerRowFunc func) { 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int j; 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (j = 0; j < height; ++j) { 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func(y, u, v, dst, width); 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) y += y_stride; 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (j & 1) { 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) u += uv_stride; 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) v += uv_stride; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dst += dst_stride; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//----------------------------------------------------------------------------- 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Main call 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WebPSamplerRowFunc WebPSamplers[MODE_LAST]; 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)extern void WebPInitSamplersSSE2(void); 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)extern void WebPInitSamplersMIPS32(void); 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebPInitSamplers(void) { 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_RGB] = YuvToRgbRow; 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_RGBA] = YuvToRgbaRow; 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_BGR] = YuvToBgrRow; 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_BGRA] = YuvToBgraRow; 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_ARGB] = YuvToArgbRow; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_RGBA_4444] = YuvToRgba4444Row; 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_RGB_565] = YuvToRgb565Row; 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_rgbA] = YuvToRgbaRow; 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_bgrA] = YuvToBgraRow; 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_Argb] = YuvToArgbRow; 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[MODE_rgbA_4444] = YuvToRgba4444Row; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If defined, use CPUInfo() to overwrite some pointers with faster versions. 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (VP8GetCPUInfo != NULL) { 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(WEBP_USE_SSE2) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (VP8GetCPUInfo(kSSE2)) { 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitSamplersSSE2(); 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // WEBP_USE_SSE2 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(WEBP_USE_MIPS32) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (VP8GetCPUInfo(kMIPS32)) { 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitSamplersMIPS32(); 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // WEBP_USE_MIPS32 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//----------------------------------------------------------------------------- 155