@@ -176,30 +176,50 @@ static f32x4 xyyToRgb(f32x4 xyy) noexcept { return xyzToRgb(xyyToXyz(xyy)); }
176176// Linear sRGB <-> LogLuv
177177static const f32x4x4 rgbToLogLuvMat = f32x4x4
178178(
179- f32x4 (0 .2209f , 0 .3390f , 0 .4184f , 0 .0f ),
180- f32x4 (0 .1138f , 0 .6780f , 0 .7319f , 0 .0f ),
181- f32x4 (0 .0102f , 0 .1130f , 0 .2969f , 0 .0f ),
179+ f32x4 (0 .1832848040f , 0 .2126390040f , 0 .252131164f , 0 .0f ),
180+ f32x4 (0 .1589263680f , 0 .7151686540f , 0 .788274765f , 0 .0f ),
181+ f32x4 (0 .0802136883f , 0 .0721923187f , 0 .283475161f , 0 .0f ),
182182 f32x4::zero
183183);
184184static const f32x4x4 logLuvToRgbMat = f32x4x4
185185(
186- f32x4 ( 6 . 0014f , -2 .7008f , -1 . 7996f , 0 .0f ),
187- f32x4 (- 1 . 3320f , 3 . 1029f , -5 .7721f , 0 .0f ),
188- f32x4 ( 0 . 3008f , - 1 . 0882f , 5 .6268f , 0 .0f ),
186+ f32x4 ( 7 . 666140550f , -2 .211964610f , -0 . 667561352f , 0 .0f ),
187+ f32x4 ( 0 . 955670714f , 1 . 668192390f , -5 .488834380f , 0 .0f ),
188+ f32x4 (- 2 . 412632940f , 0 . 201072842f , 5 .114378450f , 0 .0f ),
189189 f32x4::zero
190190);
191191
192+ static f32x4x4 calcLogLuvMat (const f32x4x4& rgbToXyzMat) noexcept
193+ {
194+ static const f32x4x4 m1 = f32x4x4
195+ (
196+ f32x4 (1 .0f , 0 .0f , 1 .0f , 0 .0f ),
197+ f32x4 (0 .0f , 1 .0f , 15 .0f , 0 .0f ),
198+ f32x4 (0 .0f , 0 .0f , 3 .0f , 0 .0f ),
199+ f32x4::zero
200+ );
201+ static const f32x4x4 m2 = f32x4x4
202+ (
203+ f32x4 (4 .0f / 9 .0f , 0 .0f , 0 .0f , 0 .0f ),
204+ f32x4 (0 .0f , 1 .0f , 0 .0f , 0 .0f ),
205+ f32x4 (0 .0f , 0 .0f , 0 .62f / 9 .0f , 0 .0f ),
206+ f32x4::zero
207+ );
208+ return dot3x3 (m2, dot3x3 (m1, rgbToXyzMat));
209+ }
210+
192211/* *
193212 * @brief Encodes linear RGB color (HDR) to the LogLuv format.
213+ * @details Encodes log2(Y) in [-20,20) range.
194214 * @param rgb target linear RGB color
195215 */
196216static uint32 rgbToLogLuv (f32x4 rgb) noexcept
197217{
198218 auto luv = max (dot3x3 (rgbToLogLuvMat, rgb), f32x4 (1e-6f ));
199- auto uv = (uint2)fma (saturate ((float2)luv / luv.getZ ()), float2 (255 .0f ), float2 (0 .5f ));
200- auto logLuv = (uint32)std::fma (saturate (std::fma (std::log2 (
201- luv.getY ()), 1 .0f / 64 .0f , 0 .5f )), 65535 .0f , 0 .5f );
202- logLuv | = (uv.x << 24u ) | (uv.y << 16u ) ;
219+ auto uv = (uint2)fma (saturate ((float2)luv / luv.getZ ()), float2 (511 .0f ), float2 (0 .5f ));
220+ auto le = (uint32)std::fma (saturate (std::fma (std::log2 (
221+ luv.getY ()), ( 1 .0f / 40 .0f ) , 0 .5f )), 16383 .0f , 0 .5f );
222+ auto logLuv = (uv.y << 23u ) | (uv.x << 14u ) | le ;
203223 return dot3 (rgb, rgb) > 0 .0f ? logLuv : 0 ;
204224}
205225/* *
@@ -208,8 +228,8 @@ static uint32 rgbToLogLuv(f32x4 rgb) noexcept
208228 */
209229static f32x4 logLuvToRgb (uint32 logLuv)
210230{
211- f32x4 luv; auto uv = float2 (uint2 (logLuv >> 24u , logLuv >> 16u ) & 255u ) * (1 .0f / 255 .0f );
212- luv.floats .y = std::exp2 (std::fma (logLuv & 65535u , ( 1 .0f / 65535 .0f ) * 64 . 0f , -32 .0f ));
231+ f32x4 luv; auto uv = float2 (uint2 (logLuv >> 14u , logLuv >> 23u ) & 511u ) * (1 .0f / 511 .0f );
232+ luv.floats .y = std::exp2 (std::fma (logLuv & 16383u , 40 .0f / 16383 .0f , -20 .0f ));
213233 luv.floats .z = luv.floats .y / uv.y ; luv.floats .x = luv.floats .z * uv.x ;
214234 return logLuv > 0 ? max (dot3x3 (logLuvToRgbMat, luv), f32x4::zero) : f32x4::zero;
215235}
0 commit comments