| 66 | |
| 67 | template<typename T, bool isYCbCr2RGB> |
| 68 | static af_array convert(const af_array& in, const af_ycc_std standard) { |
| 69 | static const float INV_219 = 0.004566210; |
| 70 | static const float INV_112 = 0.008928571; |
| 71 | const static float k[6] = {0.1140f, 0.2990f, 0.0722f, |
| 72 | 0.2126f, 0.0593f, 0.2627f}; |
| 73 | unsigned stdIdx = 0; // Default standard is AF_YCC_601 |
| 74 | switch (standard) { |
| 75 | case AF_YCC_709: stdIdx = 2; break; |
| 76 | case AF_YCC_2020: stdIdx = 4; break; |
| 77 | default: stdIdx = 0; break; |
| 78 | } |
| 79 | float kb = k[stdIdx]; |
| 80 | float kr = k[stdIdx + 1]; |
| 81 | float kl = 1.0f - kb - kr; |
| 82 | float invKl = 1 / kl; |
| 83 | |
| 84 | // extract three channels as three slices |
| 85 | // prepare sequence objects |
| 86 | // get Array objects for corresponding channel views |
| 87 | const Array<T> input = getArray<T>(in); |
| 88 | std::vector<af_seq> indices(4, af_span); |
| 89 | |
| 90 | indices[2] = {0, 0, 1}; |
| 91 | Array<T> X = createSubArray(input, indices, false); |
| 92 | |
| 93 | indices[2] = {1, 1, 1}; |
| 94 | Array<T> Y = createSubArray(input, indices, false); |
| 95 | |
| 96 | indices[2] = {2, 2, 1}; |
| 97 | Array<T> Z = createSubArray(input, indices, false); |
| 98 | |
| 99 | if (isYCbCr2RGB) { |
| 100 | const dim4& dims = X.dims(); |
| 101 | Array<T> yc = createValueArray<T>(dims, 16); |
| 102 | Array<T> cc = createValueArray<T>(dims, 128); |
| 103 | Array<T> Y_ = arithOp<T, af_sub_t>(X, yc, dims); |
| 104 | Array<T> Cb_ = arithOp<T, af_sub_t>(Y, cc, dims); |
| 105 | Array<T> Cr_ = arithOp<T, af_sub_t>(Z, cc, dims); |
| 106 | Array<T> R = mix<T>(Y_, Cr_, INV_219, INV_112 * (1 - kr)); |
| 107 | Array<T> G = |
| 108 | mix<T>(Y_, Cr_, Cb_, INV_219, INV_112 * (kr - 1) * kr * invKl, |
| 109 | INV_112 * (kb - 1) * kb * invKl); |
| 110 | Array<T> B = mix<T>(Y_, Cb_, INV_219, INV_112 * (1 - kb)); |
| 111 | // join channels |
| 112 | dim4 odims(R.dims()[0], R.dims()[1], 3); |
| 113 | Array<T> rgbout = createEmptyArray<T>(odims); |
| 114 | join<T>(rgbout, 2, {R, G, B}); |
| 115 | return getHandle(rgbout); |
| 116 | } |
| 117 | Array<T> Ey = mix<T>(X, Y, Z, kr, kl, kb); |
| 118 | Array<T> Ecr = |
| 119 | mix<T>(X, Y, Z, 0.5, 0.5 * kl / (kr - 1), 0.5 * kb / (kr - 1)); |
| 120 | Array<T> Ecb = |
| 121 | mix<T>(X, Y, Z, 0.5 * kr / (kb - 1), 0.5 * kl / (kb - 1), 0.5); |
| 122 | Array<T> Y_ = digitize<T>(Ey, 219.0, 16.0); |
| 123 | Array<T> Cr = digitize<T>(Ecr, 224.0, 128.0); |
| 124 | Array<T> Cb = digitize<T>(Ecb, 224.0, 128.0); |
| 125 | // join channels |