upsampling.c revision a2415724fb3466168b2af5b08bd94ba732c0e753
1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved. 2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 3a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// This code is licensed under the same terms as WebM: 4a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Software License Agreement: http://www.webmproject.org/license/software/ 5a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 6a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 7a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// YUV to RGB upsampling functions. 9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Author: somnath@google.com (Somnath Banerjee) 11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./dsp.h" 13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./yuv.h" 14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraextern "C" { 17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 19a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Fancy upsampler 21a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 22a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef FANCY_UPSAMPLING 23a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Fancy upsampling functions to convert YUV to RGB 25a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; 26a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 27a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Given samples laid out in a square as: 28a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// [a b] 29a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// [c d] 30a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// we interpolate u/v as: 31a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 32a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// We process u and v together stashed into 32bit (16bit each). 35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define LOAD_UV(u,v) ((u) | ((v) << 16)) 36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ 38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ 39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* top_u, const uint8_t* top_v, \ 40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* cur_u, const uint8_t* cur_v, \ 41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ 42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int x; \ 43a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int last_pixel_pair = (len - 1) >> 1; \ 44a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ 45a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ 46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top_y) { \ 47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ 48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ 49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bottom_y) { \ 51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ 52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ 53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (x = 1; x <= last_pixel_pair; ++x) { \ 55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ 56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ 57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora /* precompute invariant values associated with first and second diagonals*/\ 58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ 59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ 60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ 61a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top_y) { \ 62a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ 63a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ 64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ 65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora top_dst + (2 * x - 1) * XSTEP); \ 66a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ 67a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora top_dst + (2 * x - 0) * XSTEP); \ 68a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 69a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bottom_y) { \ 70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ 71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv1 = (diag_12 + uv) >> 1; \ 72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ 73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora bottom_dst + (2 * x - 1) * XSTEP); \ 74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ 75a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora bottom_dst + (2 * x + 0) * XSTEP); \ 76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora tl_uv = t_uv; \ 78a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora l_uv = uv; \ 79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!(len & 1)) { \ 81a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top_y) { \ 82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ 83a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ 84a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora top_dst + (len - 1) * XSTEP); \ 85a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bottom_y) { \ 87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ 88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ 89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora bottom_dst + (len - 1) * XSTEP); \ 90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 91a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// All variants implemented. 95a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) 96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) 97a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) 98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) 99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) 100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) 101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraUPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) 102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef LOAD_UV 104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef UPSAMPLE_FUNC 105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif // FANCY_UPSAMPLING 107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// simple point-sampling 110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define SAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ 112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ 113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* u, const uint8_t* v, \ 114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ 115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; \ 116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < len - 1; i += 2) { \ 117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[0], u[0], v[0], top_dst); \ 118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[1], u[0], v[0], top_dst + XSTEP); \ 119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[0], u[0], v[0], bottom_dst); \ 120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[1], u[0], v[0], bottom_dst + XSTEP); \ 121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora top_y += 2; \ 122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora bottom_y += 2; \ 123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u++; \ 124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v++; \ 125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora top_dst += 2 * XSTEP; \ 126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora bottom_dst += 2 * XSTEP; \ 127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (i == len - 1) { /* last one */ \ 129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[0], u[0], v[0], top_dst); \ 130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bottom_y[0], u[0], v[0], bottom_dst); \ 131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// All variants implemented. 135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleRgbLinePair, VP8YuvToRgb, 3) 136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleBgrLinePair, VP8YuvToBgr, 3) 137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleRgbaLinePair, VP8YuvToRgba, 4) 138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleBgraLinePair, VP8YuvToBgra, 4) 139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleArgbLinePair, VP8YuvToArgb, 4) 140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleRgba4444LinePair, VP8YuvToRgba4444, 2) 141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraSAMPLE_FUNC(SampleRgb565LinePair, VP8YuvToRgb565, 2) 142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef SAMPLE_FUNC 144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraconst WebPSampleLinePairFunc WebPSamplers[MODE_LAST] = { 146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgbLinePair, // MODE_RGB 147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgbaLinePair, // MODE_RGBA 148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleBgrLinePair, // MODE_BGR 149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleBgraLinePair, // MODE_BGRA 150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleArgbLinePair, // MODE_ARGB 151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgba4444LinePair, // MODE_RGBA_4444 152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgb565LinePair, // MODE_RGB_565 153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgbaLinePair, // MODE_rgbA 154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleBgraLinePair, // MODE_bgrA 155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleArgbLinePair, // MODE_Argb 156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora SampleRgba4444LinePair // MODE_rgbA_4444 157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}; 158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 159a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 160a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 161a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if !defined(FANCY_UPSAMPLING) 162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ 163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ 164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* top_u, const uint8_t* top_v, \ 165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* bot_u, const uint8_t* bot_v, \ 166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* top_dst, uint8_t* bot_dst, int len) { \ 167a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int half_len = len >> 1; \ 168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int x; \ 169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top_dst != NULL) { \ 170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (x = 0; x < half_len; ++x) { \ 171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ 172a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ 173a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ 175a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 176a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (bot_dst != NULL) { \ 177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (x = 0; x < half_len; ++x) { \ 178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ 179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ 180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (len & 1) FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x); \ 182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } \ 183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraDUAL_SAMPLE_FUNC(DualLineSamplerBGRA, VP8YuvToBgra) 186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraDUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) 187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef DUAL_SAMPLE_FUNC 188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif // !FANCY_UPSAMPLING 190a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { 192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPInitUpsamplers(); 193a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8YUVInit(); 194a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef FANCY_UPSAMPLING 195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; 196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#else 197a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return (alpha_is_last ? DualLineSamplerBGRA : DualLineSamplerARGB); 198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 200a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// YUV444 converter 203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define YUV444_FUNC(FUNC_NAME, FUNC, XSTEP) \ 205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ 206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* dst, int len) { \ 207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; \ 208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ 209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 210a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 211a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb, 3) 212a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr, 3) 213a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba, 4) 214a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra, 4) 215a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToArgb, VP8YuvToArgb, 4) 216a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToRgba4444, VP8YuvToRgba4444, 2) 217a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraYUV444_FUNC(Yuv444ToRgb565, VP8YuvToRgb565, 2) 218a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 219a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef YUV444_FUNC 220a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 221a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraconst WebPYUV444Converter WebPYUV444Converters[MODE_LAST] = { 222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgb, // MODE_RGB 223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgba, // MODE_RGBA 224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToBgr, // MODE_BGR 225a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToBgra, // MODE_BGRA 226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToArgb, // MODE_ARGB 227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgba4444, // MODE_RGBA_4444 228a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgb565, // MODE_RGB_565 229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgba, // MODE_rgbA 230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToBgra, // MODE_bgrA 231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToArgb, // MODE_Argb 232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Yuv444ToRgba4444 // MODE_rgbA_4444 233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}; 234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 236a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Premultiplied modes 237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// non dithered-modes 239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) 241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), 242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if 1 // (int)(x * a / 255.) 244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define MULTIPLIER(a) ((a) * 32897UL) 245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) 246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#else // (int)(x * a / 255. + .5) 247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define MULTIPLIER(a) ((a) * 65793UL) 248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define PREMULTIPLY(x, m) (((x) * (m) + (1UL << 23)) >> 24) 249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, 252a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int w, int h, int stride) { 253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (h-- > 0) { 254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); 255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); 256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < w; ++i) { 258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t a = alpha[4 * i]; 259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (a != 0xff) { 260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t mult = MULTIPLIER(a); 261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); 262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); 263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); 264a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 265a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgba += stride; 267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef MULTIPLIER 270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef PREMULTIPLY 271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// rgbA4444 273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 275a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint8_t dither_hi(uint8_t x) { 277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return (x & 0xf0) | (x >> 4); 278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint8_t dither_lo(uint8_t x) { 281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return (x & 0x0f) | (x << 4); 282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 283a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { 285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return (x * m) >> 16; 286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyAlphaMultiply4444(uint8_t* rgba4444, 289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int w, int h, int stride) { 290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (h-- > 0) { 291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int i; 292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (i = 0; i < w; ++i) { 293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t a = (rgba4444[2 * i + 1] & 0x0f); 294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint32_t mult = MULTIPLIER(a); 295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t r = multiply(dither_hi(rgba4444[2 * i + 0]), mult); 296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t g = multiply(dither_lo(rgba4444[2 * i + 0]), mult); 297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t b = multiply(dither_hi(rgba4444[2 * i + 1]), mult); 298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgba4444[2 * i + 0] = (r & 0xf0) | ((g >> 4) & 0x0f); 299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgba4444[2 * i + 1] = (b & 0xf0) | a; 300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 301a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora rgba4444 += stride; 302a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 303a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 304a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef MULTIPLIER 305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int) 307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora = ApplyAlphaMultiply; 308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int) 309a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora = ApplyAlphaMultiply4444; 310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main call 313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid WebPInitUpsamplers(void) { 315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef FANCY_UPSAMPLING 316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; 317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; 318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; 319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; 320a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; 321a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; 322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; 323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // If defined, use CPUInfo() to overwrite some pointers with faster versions. 325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8GetCPUInfo != NULL) { 326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if defined(WEBP_USE_SSE2) 327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8GetCPUInfo(kSSE2)) { 328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPInitUpsamplersSSE2(); 329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif // FANCY_UPSAMPLING 333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid WebPInitPremultiply(void) { 336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPApplyAlphaMultiply = ApplyAlphaMultiply; 337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply4444; 338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef FANCY_UPSAMPLING 340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; 341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; 342a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; 343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; 344a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 345a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8GetCPUInfo != NULL) { 346a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if defined(WEBP_USE_SSE2) 347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8GetCPUInfo(kSSE2)) { 348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPInitPremultiplySSE2(); 349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif // FANCY_UPSAMPLING 353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} // extern "C" 357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 358