dxt.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #include "dxt.h"
  2. #include "libc.h"
  3. #include <stdint.h>
  4. static uint16_t dxtColorSum(int m1, uint16_t c1, int m2, uint16_t c2, int add, int denom) {
  5. /*
  6. const int mask_rb = 0xf81f, mask_g = 0x07e0;
  7. const uint32_t
  8. rb1 = c1 & mask_rb, g1 = c1 & mask_g,
  9. rb2 = c2 & mask_rb, g2 = c2 & mask_g;
  10. add |= (add << 5) | (add << 11);
  11. return
  12. (((m1 * rb1 + m2 * rb2 + add) / denom) & mask_rb) |
  13. (((m1 * g1 + m2 * g2 + add) / denom) & mask_g);
  14. */
  15. const int mask_r = 0xf800, shift_r = 11;
  16. const int mask_g = 0x07e0, shift_g = 5;
  17. const int mask_b = 0x001f, shift_b = 0;
  18. const int r =
  19. (((c1 & mask_r) >> shift_r) * m1 +
  20. ((c2 & mask_r) >> shift_r) * m2 + add) / denom;
  21. const int g =
  22. (((c1 & mask_g) >> shift_g) * m1 +
  23. ((c2 & mask_g) >> shift_g) * m2 + add) / denom;
  24. const int b =
  25. (((c1 & mask_b) >> shift_b) * m1 +
  26. ((c2 & mask_b) >> shift_b) * m2 + add) / denom;
  27. return ((r << shift_r) & mask_r) | ((g << shift_g) & mask_g) | ((b << shift_b) & mask_b);
  28. }
  29. void dxtUnpack(struct DXTUnpackContext ctx, int offset) {
  30. if (ctx.width < 4 || ctx.height < 4 || ctx.width & 3 || ctx.height & 3)
  31. return;
  32. const uint16_t transparent = 0;
  33. const uint8_t *src = (const uint8_t*)ctx.packed;
  34. for (int y = 0; y < ctx.height; y+=4) {
  35. uint16_t *dst_4x4 = (uint16_t*)ctx.output + ctx.width * y;
  36. for (int x = 0; x < ctx.width; x+=4, dst_4x4 += 4, src += offset) {
  37. uint16_t c[4];
  38. memcpy(c, src, 2);
  39. memcpy(c+1, src + 2, 2);
  40. if (c[0] > c[1]) {
  41. c[2] = dxtColorSum(2, c[0], 1, c[1], 1, 3);
  42. c[3] = dxtColorSum(1, c[0], 2, c[1], 1, 3);
  43. } else {
  44. c[2] = dxtColorSum(1, c[0], 1, c[1], 0, 2);
  45. c[3] = transparent;
  46. }
  47. uint16_t *pix = dst_4x4;
  48. for (int r = 0; r < 4; ++r, pix += ctx.width) {
  49. const uint8_t bitmap = src[4 + r];
  50. pix[3] = c[(bitmap >> 6) & 3];
  51. pix[2] = c[(bitmap >> 4) & 3];
  52. pix[1] = c[(bitmap >> 2) & 3];
  53. pix[0] = c[(bitmap >> 0) & 3];
  54. } /* for all rows in 4x4 */
  55. } /* for x */
  56. } /* for y */
  57. }
  58. void dxt1Unpack(struct DXTUnpackContext ctx) {
  59. dxtUnpack(ctx, 8);
  60. }
  61. void dxt5Unpack(struct DXTUnpackContext ctx) {
  62. ctx.packed = ((char*)ctx.packed) + 8;
  63. dxtUnpack(ctx, 16);
  64. }