dxt.c 1.8 KB

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