Interpolates between two endpoints, then does a final unquantization step
| 479 | |
| 480 | // Interpolates between two endpoints, then does a final unquantization step |
| 481 | Color interpolate(RGBf e0, RGBf e1, const IndexInfo &index, bool isSigned) { |
| 482 | static constexpr uint32_t weights3[] = {0, 9, 18, 27, 37, 46, 55, 64}; |
| 483 | static constexpr uint32_t weights4[] = {0, 4, 9, 13, 17, 21, 26, 30, |
| 484 | 34, 38, 43, 47, 51, 55, 60, 64}; |
| 485 | static constexpr uint32_t const *weightsN[] = { |
| 486 | nullptr, nullptr, nullptr, weights3, weights4 |
| 487 | }; |
| 488 | auto weights = weightsN[index.numBits]; |
| 489 | assert(weights != nullptr); |
| 490 | Color color; |
| 491 | uint32_t e0Weight = 64 - weights[index.value]; |
| 492 | uint32_t e1Weight = weights[index.value]; |
| 493 | |
| 494 | for (int i = 0; i < RGBfChannels; i++) { |
| 495 | int32_t e0Channel = e0.channel[i]; |
| 496 | int32_t e1Channel = e1.channel[i]; |
| 497 | |
| 498 | if (isSigned) { |
| 499 | e0Channel = extendSign(e0Channel, 16); |
| 500 | e1Channel = extendSign(e1Channel, 16); |
| 501 | } |
| 502 | |
| 503 | int32_t e0Value = e0Channel * e0Weight; |
| 504 | int32_t e1Value = e1Channel * e1Weight; |
| 505 | |
| 506 | uint32_t tmp = ((e0Value + e1Value + 32) >> 6); |
| 507 | |
| 508 | // Need to unquantize value to limit it to the legal range of half-precision |
| 509 | // floats. We do this by scaling by 31/32 or 31/64 depending on if the value |
| 510 | // is signed or unsigned. |
| 511 | if (isSigned) { |
| 512 | tmp = ((tmp & 0x80000000) != 0) ? (((~tmp + 1) * 31) >> 5) | 0x8000 : (tmp * 31) >> 5; |
| 513 | // Don't return -0.0f, just normalize it to 0.0f. |
| 514 | if (tmp == 0x8000) |
| 515 | tmp = 0; |
| 516 | } else { |
| 517 | tmp = (tmp * 31) >> 6; |
| 518 | } |
| 519 | |
| 520 | color.channel[i] = (uint16_t) tmp; |
| 521 | } |
| 522 | |
| 523 | return color; |
| 524 | } |
| 525 | |
| 526 | enum DataType { |
| 527 | // Endpoints |