Initialize B44 exp/log lookup tables (matches OpenEXR algorithm)
| 3709 | |
| 3710 | // Initialize B44 exp/log lookup tables (matches OpenEXR algorithm) |
| 3711 | static void InitB44Tables() { |
| 3712 | if (g_b44_tables_initialized) return; |
| 3713 | |
| 3714 | // Generate tables per OpenEXR's b44_table_init.c |
| 3715 | for (int i = 0; i < 65536; i++) { |
| 3716 | unsigned short x = static_cast<unsigned short>(i); |
| 3717 | |
| 3718 | // expTable: convertFromLinear - exp(half / 8) |
| 3719 | if ((x & 0x7c00) == 0x7c00) { |
| 3720 | // infinity/nan -> 0 |
| 3721 | g_b44_exp_table[i] = 0; |
| 3722 | } else if (x >= 0x558c && x < 0x8000) { |
| 3723 | // >= 8 * log(HALF_MAX) -> HALF_MAX |
| 3724 | g_b44_exp_table[i] = 0x7bff; |
| 3725 | } else { |
| 3726 | float f = B44HalfToFloat(x); |
| 3727 | f = static_cast<float>(std::exp(static_cast<double>(f) / 8.0)); |
| 3728 | g_b44_exp_table[i] = B44FloatToHalf(f); |
| 3729 | } |
| 3730 | |
| 3731 | // logTable: convertToLinear - 8 * log(half) |
| 3732 | if ((x & 0x7c00) == 0x7c00) { |
| 3733 | // infinity/nan -> 0 |
| 3734 | g_b44_log_table[i] = 0; |
| 3735 | } else if (x > 0x8000) { |
| 3736 | // negative (excluding -0.0) -> 0 |
| 3737 | g_b44_log_table[i] = 0; |
| 3738 | } else { |
| 3739 | float f = B44HalfToFloat(x); |
| 3740 | if (f <= 0.0f) { |
| 3741 | g_b44_log_table[i] = 0; |
| 3742 | } else { |
| 3743 | f = static_cast<float>(8.0 * std::log(static_cast<double>(f))); |
| 3744 | g_b44_log_table[i] = B44FloatToHalf(f); |
| 3745 | } |
| 3746 | } |
| 3747 | } |
| 3748 | |
| 3749 | g_b44_tables_initialized = true; |
| 3750 | } |
| 3751 | |
| 3752 | // Convert half to linear-log space (for p_linear channels) |
| 3753 | static inline unsigned short B44ConvertFromLinear(unsigned short h) { |
no test coverage detected