|
26 | 26 | #include "Simd/SimdMath.h"
|
27 | 27 | #include "Simd/SimdLog.h"
|
28 | 28 |
|
| 29 | +#define SIMD_BGR_TO_LAB_OPENCV_COMPATIBILITY |
| 30 | + |
29 | 31 | namespace Simd
|
30 | 32 | {
|
31 | 33 | namespace Base
|
32 | 34 | {
|
33 |
| -#define SIMD_BGR_TO_LAB_OPENCV_COMPATIBILITY |
| 35 | + uint16_t LabGammaTab[LabGammaTabSize]; |
| 36 | + uint16_t LabCbrtTab[LabCbrtTabSize]; |
| 37 | + uint32_t LabCoeffsTab[9]; |
34 | 38 |
|
35 |
| - namespace LabV1 |
| 39 | + SIMD_INLINE float ApplyGamma(float x) |
36 | 40 | {
|
37 |
| - inline double FromRaw(uint64_t raw) |
38 |
| - { |
39 |
| - return *((double*)&raw); |
40 |
| - } |
41 |
| - |
42 |
| - SIMD_INLINE float mullAdd(float a, float b, float c) |
43 |
| - { |
44 |
| - return a * b + c; |
45 |
| - } |
46 |
| - |
47 |
| -#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) |
48 |
| - const int xyz_shift = 12; |
49 |
| - |
50 |
| - //const double D65[3] = { 0.950456, 1., 1.088754 }; |
51 |
| - const double D65[3] = { FromRaw(0x3fee6a22b3892ee8), |
52 |
| - 1.0 , |
53 |
| - FromRaw(0x3ff16b8950763a19) }; |
54 |
| - |
55 |
| - //static const double sRGB2XYZ_D65[] = |
56 |
| - //{ |
57 |
| - // 0.412453, 0.357580, 0.180423, |
58 |
| - // 0.212671, 0.715160, 0.072169, |
59 |
| - // 0.019334, 0.119193, 0.950227 |
60 |
| - //}; |
61 |
| - |
62 |
| - const double sRGB2XYZ_D65[] = |
63 |
| - { |
64 |
| - FromRaw(0x3fda65a14488c60d), |
65 |
| - FromRaw(0x3fd6e297396d0918), |
66 |
| - FromRaw(0x3fc71819d2391d58), |
67 |
| - FromRaw(0x3fcb38cda6e75ff6), |
68 |
| - FromRaw(0x3fe6e297396d0918), |
69 |
| - FromRaw(0x3fb279aae6c8f755), |
70 |
| - FromRaw(0x3f93cc4ac6cdaf4b), |
71 |
| - FromRaw(0x3fbe836eb4e98138), |
72 |
| - FromRaw(0x3fee68427418d691) |
73 |
| - }; |
74 |
| - |
75 |
| - enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 }; |
76 |
| - |
77 |
| - static const float GammaTabScale((int)GAMMA_TAB_SIZE); |
78 |
| - |
79 |
| - static uint16_t sRGBGammaTab_b[256]; |
80 |
| - |
81 |
| -#undef lab_shift |
82 |
| -#define lab_shift xyz_shift |
83 |
| -#define gamma_shift 3 |
84 |
| -#define lab_shift2 (lab_shift + gamma_shift) |
85 |
| -#define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift)) |
86 |
| - static uint16_t LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B]; |
87 |
| - |
88 |
| -//all constants should be presented through integers to keep bit-exactness |
89 |
| - static const double gammaThreshold = double(809) / double(20000); // 0.04045 |
90 |
| - static const double gammaInvThreshold = double(7827) / double(2500000); // 0.0031308 |
91 |
| - static const double gammaLowScale = double(323) / double(25); // 12.92 |
92 |
| - static const double gammaPower = double(12) / double(5); // 2.4 |
93 |
| - static const double gammaXshift = double(11) / double(200); // 0.055 |
| 41 | + return x <= 0.04045f ? x * (1.f / 12.92f) : (float)std::pow((double)(x + 0.055) * (1. / 1.055), 2.4); |
| 42 | + } |
94 | 43 |
|
95 |
| - static const float lthresh = float(216) / float(24389); // 0.008856f = (6/29)^3 |
96 |
| - static const float lscale = float(841) / float(108); // 7.787f = (29/3)^3/(29*4) |
97 |
| - static const float lbias = float(16) / float(116); |
| 44 | + SIMD_INLINE float ApplyCbrt(float x) |
| 45 | + { |
| 46 | + static const float threshold = float(216) / float(24389); |
| 47 | + static const float scale = float(841) / float(108); |
| 48 | + static const float bias = float(16) / float(116); |
| 49 | + return x < threshold ? (x * scale + bias) : cbrt(x); |
| 50 | + } |
98 | 51 |
|
99 |
| - static inline float applyGamma(float x) |
| 52 | + static bool LabTabsInited = false; |
| 53 | + void LabInitTabs() |
| 54 | + { |
| 55 | + if (LabTabsInited) |
| 56 | + return; |
| 57 | + const float intScale(255 * (1 << LAB_GAMMA_SHIFT)); |
| 58 | + for (int i = 0; i < LabGammaTabSize; i++) |
100 | 59 | {
|
101 |
| - //return x <= 0.04045f ? x*(1.f/12.92f) : (float)std::pow((double)(x + 0.055)*(1./1.055), 2.4); |
102 |
| - |
103 |
| - double xd = x; |
104 |
| - return (xd <= gammaThreshold ? |
105 |
| - xd / gammaLowScale : |
106 |
| - pow((xd + gammaXshift) / (1.0 + gammaXshift), gammaPower)); |
| 60 | + float x = float(i) / 255.0f; |
| 61 | + LabGammaTab[i] = (uint16_t)(Round(intScale * ApplyGamma(x))); |
107 | 62 | }
|
108 |
| - |
109 |
| - static void initLabTabs() |
| 63 | + const float tabScale(1.0 / (255.0 * (1 << LAB_GAMMA_SHIFT))); |
| 64 | + const float shift2(1 << LAB_SHIFT2); |
| 65 | + for (int i = 0; i < LabCbrtTabSize; i++) |
110 | 66 | {
|
111 |
| - static bool initialized = false; |
112 |
| - if (!initialized) |
113 |
| - { |
114 |
| - float scale = 1.0f / float(GammaTabScale); |
115 |
| - static const float intScale(255 * (1 << gamma_shift)); |
116 |
| - for (int i = 0; i < 256; i++) |
117 |
| - { |
118 |
| - float x = float(i) / 255.0f; |
119 |
| - sRGBGammaTab_b[i] = (uint16_t)(Round(intScale * applyGamma(x))); |
120 |
| - } |
121 |
| - |
122 |
| - static const float cbTabScale(1.0 / (255.0 * (1 << gamma_shift))); |
123 |
| - static const float lshift2(1 << lab_shift2); |
124 |
| - for (int i = 0; i < LAB_CBRT_TAB_SIZE_B; i++) |
125 |
| - { |
126 |
| - float x = cbTabScale * float(i); |
127 |
| - LabCbrtTab_b[i] = (uint16_t)(Round(lshift2 * (x < lthresh ? mullAdd(x, lscale, lbias) : cbrt(x)))); |
128 |
| - } |
129 |
| -#if defined(SIMD_BGR_TO_LAB_OPENCV_COMPATIBILITY) |
130 |
| - if(LabCbrtTab_b[324] == 17746) |
131 |
| - LabCbrtTab_b[324] = 17745; |
132 |
| - if (LabCbrtTab_b[49] == 9455) |
133 |
| - LabCbrtTab_b[49] = 9454; |
134 |
| -#endif |
135 |
| - initialized = true; |
136 |
| - } |
| 67 | + float x = tabScale * float(i); |
| 68 | + LabCbrtTab[i] = (uint16_t)Round(shift2 * ApplyCbrt(x)); |
137 | 69 | }
|
138 |
| - |
139 |
| - struct RGB2Lab_b |
140 |
| - { |
141 |
| - typedef uint8_t channel_type; |
142 |
| - |
143 |
| - RGB2Lab_b(int _srccn, int blueIdx) |
144 |
| - : srccn(_srccn) |
145 |
| - { |
146 |
| - initLabTabs(); |
147 |
| - |
148 |
| - double whitePt[3]; |
149 |
| - for (int i = 0; i < 3; i++) |
150 |
| - whitePt[i] = D65[i]; |
151 |
| - |
152 |
| - const double lshift(1 << lab_shift); |
153 |
| - for (int i = 0; i < 3; i++) |
154 |
| - { |
155 |
| - double c[3]; |
156 |
| - for (int j = 0; j < 3; j++) |
157 |
| - c[j] = sRGB2XYZ_D65[i * 3 + j]; |
158 |
| - coeffs[i * 3 + (blueIdx ^ 2)] = Round(lshift * c[0] / whitePt[i]); |
159 |
| - coeffs[i * 3 + 1] = Round(lshift * c[1] / whitePt[i]); |
160 |
| - coeffs[i * 3 + blueIdx] = Round(lshift * c[2] / whitePt[i]); |
161 |
| - |
162 |
| - assert(coeffs[i * 3] >= 0 && coeffs[i * 3 + 1] >= 0 && coeffs[i * 3 + 2] >= 0 && |
163 |
| - coeffs[i * 3] + coeffs[i * 3 + 1] + coeffs[i * 3 + 2] < 2 * (1 << lab_shift)); |
164 |
| - } |
165 |
| - } |
166 |
| - |
167 |
| - void operator()(const uint8_t* src, uint8_t* dst, int n) const |
168 |
| - { |
169 |
| - const int Lscale = (116 * 255 + 50) / 100; |
170 |
| - const int Lshift = -((16 * 255 * (1 << lab_shift2) + 50) / 100); |
171 |
| - const uint16_t* tab = sRGBGammaTab_b; |
172 |
| - int i, scn = srccn; |
173 |
| - int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], |
174 |
| - C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5], |
175 |
| - C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8]; |
176 |
| - |
177 |
| - for (int i = 0; i < n; i++, src += scn, dst += 3) |
178 |
| - { |
179 |
| - int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]]; |
180 |
| - int fX = LabCbrtTab_b[CV_DESCALE(R * C0 + G * C1 + B * C2, lab_shift)]; |
181 |
| - int fY = LabCbrtTab_b[CV_DESCALE(R * C3 + G * C4 + B * C5, lab_shift)]; |
182 |
| - int fZ = LabCbrtTab_b[CV_DESCALE(R * C6 + G * C7 + B * C8, lab_shift)]; |
183 |
| - |
184 |
| - int L = CV_DESCALE(Lscale * fY + Lshift, lab_shift2); |
185 |
| - int a = CV_DESCALE(500 * (fX - fY) + 128 * (1 << lab_shift2), lab_shift2); |
186 |
| - int b = CV_DESCALE(200 * (fY - fZ) + 128 * (1 << lab_shift2), lab_shift2); |
187 |
| - |
188 |
| -#if defined(_WIN32) && 0 |
189 |
| - if (L == 45 && a == 165) |
190 |
| - { |
191 |
| - std::cout << i << " old Lab = {" << L << ", " << a << ", " << b << "}"; |
192 |
| - |
193 |
| - int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]]; |
194 |
| - int fX = LabCbrtTab_b[CV_DESCALE(R * C0 + G * C1 + B * C2, lab_shift)]; |
195 |
| - int fY = LabCbrtTab_b[CV_DESCALE(R * C3 + G * C4 + B * C5, lab_shift)] - 1; |
196 |
| - int fZ = LabCbrtTab_b[CV_DESCALE(R * C6 + G * C7 + B * C8, lab_shift)]; |
197 |
| - |
198 |
| - int L = CV_DESCALE(Lscale * fY + Lshift, lab_shift2); |
199 |
| - int a = CV_DESCALE(500 * (fX - fY) + 128 * (1 << lab_shift2), lab_shift2); |
200 |
| - int b = CV_DESCALE(200 * (fY - fZ) + 128 * (1 << lab_shift2), lab_shift2); |
201 |
| - |
202 |
| - std::cout << " new Lab = {" << L << ", " << a << ", " << b << "}"; |
203 |
| - std::cout << " index " << CV_DESCALE(R * C3 + G * C4 + B * C5, lab_shift); |
204 |
| - std::cout << " value " << LabCbrtTab_b[CV_DESCALE(R * C3 + G * C4 + B * C5, lab_shift)]; |
205 |
| - std::cout << std::endl; |
206 |
| - exit(0); |
207 |
| - } |
| 70 | +#if defined(SIMD_BGR_TO_LAB_OPENCV_COMPATIBILITY) |
| 71 | + if (LabCbrtTab[324] == 17746) |
| 72 | + LabCbrtTab[324] = 17745; |
| 73 | + if (LabCbrtTab[49] == 9455) |
| 74 | + LabCbrtTab[49] = 9454; |
208 | 75 | #endif
|
209 |
| - dst[0] = Base::RestrictRange(L); |
210 |
| - dst[1] = Base::RestrictRange(a); |
211 |
| - dst[2] = Base::RestrictRange(b); |
212 |
| - } |
213 |
| - } |
214 |
| - |
215 |
| - int srccn; |
216 |
| - int coeffs[9]; |
217 |
| - }; |
| 76 | + const double D65[3] = { 0.950456, 1., 1.088754 }; |
| 77 | + const double sRGB2XYZ_D65[9] = { 0.412453, 0.357580, 0.180423, 0.212671, 0.715160, 0.072169, 0.019334, 0.119193, 0.950227 }; |
| 78 | + const double shift(1 << LAB_SHIFT); |
| 79 | + for (int i = 0; i < 3; i++) |
| 80 | + for (int j = 0; j < 3; j++) |
| 81 | + LabCoeffsTab[i * 3 + j] = Round(shift * sRGB2XYZ_D65[i * 3 + j] / D65[i]); |
| 82 | + LabTabsInited = true; |
218 | 83 | }
|
219 | 84 |
|
| 85 | + //-------------------------------------------------------------------------------------------------- |
| 86 | + |
220 | 87 | void BgrToLab(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* lab, size_t labStride)
|
221 | 88 | {
|
222 |
| -#if 1 |
223 |
| - LabV1::RGB2Lab_b _lab(3, 0); |
| 89 | + LabInitTabs(); |
224 | 90 | for (size_t row = 0; row < height; ++row)
|
225 | 91 | {
|
226 |
| - const uint8_t* pBgr = bgr + row * bgrStride; |
| 92 | + const uint8_t* pBgr = bgr + row * bgrStride, * pEnd = pBgr + width * 3; |
227 | 93 | uint8_t* pLab = lab + row * labStride;
|
228 |
| - _lab(pBgr, pLab, width); |
| 94 | + for (; pBgr < pEnd; pBgr += 3, pLab += 3) |
| 95 | + RgbToLab(pBgr[2], pBgr[1], pBgr[0], pLab); |
229 | 96 | }
|
230 |
| - |
231 |
| -#else |
232 |
| - for (size_t row = 0; row < height; ++row) |
233 |
| - { |
234 |
| - const uint8_t* pBgr = bgr + row * bgrStride; |
235 |
| - uint8_t* pLab = lab + row * labStride; |
236 |
| - for (const uint8_t* pBgrEnd = pBgr + width * 3; pBgr < pBgrEnd; pBgr += 3, pLab += 3) |
237 |
| - BgrToLab(pBgr[0], pBgr[1], pBgr[2], pLab); |
238 |
| - } |
239 |
| -#endif |
240 | 97 | }
|
241 | 98 | }
|
242 | 99 | }
|
|
0 commit comments