bng.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. #ifndef BNG_H_
  2. #define BNG_H_
  3. #define BNG_MAGIC 0x21474E42
  4. #if defined(__GNUC__) || defined(__clang__)
  5. # define PACKED __attribute__((packed))
  6. #else
  7. # warning "Packed attributes for struct is not implemented for this compiler. This may result in a program working incorrectly. Feel free to fix that and submit a Pull Request to https://github.com/tsoding/bng"
  8. # define PACKED
  9. #endif
  10. struct Bng_Pixel_Format
  11. {
  12. uint8_t red_byte; // 0
  13. uint8_t green_byte; // 1
  14. uint8_t blue_byte; // 2
  15. uint8_t alpha_byte; // 3
  16. } PACKED;
  17. int bng_pixel_format_equals(struct Bng_Pixel_Format a, struct Bng_Pixel_Format b)
  18. {
  19. return a.red_byte == b.red_byte &&
  20. a.green_byte == b.green_byte &&
  21. a.blue_byte == b.blue_byte &&
  22. a.alpha_byte == b.alpha_byte;
  23. }
  24. const struct Bng_Pixel_Format RGBA = {0, 1, 2, 3};
  25. const struct Bng_Pixel_Format GRBA = {1, 0, 2, 3};
  26. const struct Bng_Pixel_Format BGRA = {2, 1, 0, 3};
  27. const struct Bng_Pixel_Format GBRA = {1, 2, 0, 3};
  28. const struct Bng_Pixel_Format BRGA = {2, 0, 1, 3};
  29. const struct Bng_Pixel_Format RBGA = {0, 2, 1, 3};
  30. const struct Bng_Pixel_Format ABGR = {3, 2, 1, 0};
  31. const struct Bng_Pixel_Format BAGR = {2, 3, 1, 0};
  32. const struct Bng_Pixel_Format BGAR = {2, 1, 3, 0};
  33. const struct Bng_Pixel_Format AGBR = {3, 1, 2, 0};
  34. const struct Bng_Pixel_Format GABR = {1, 3, 2, 0};
  35. const struct Bng_Pixel_Format GBAR = {1, 2, 3, 0};
  36. const struct Bng_Pixel_Format ARGB = {3, 0, 1, 2};
  37. const struct Bng_Pixel_Format RAGB = {0, 3, 1, 2};
  38. const struct Bng_Pixel_Format RGAB = {0, 1, 3, 2};
  39. const struct Bng_Pixel_Format AGRB = {3, 1, 0, 2};
  40. const struct Bng_Pixel_Format GARB = {1, 3, 0, 2};
  41. const struct Bng_Pixel_Format GRAB = {1, 0, 3, 2};
  42. const struct Bng_Pixel_Format ARBG = {3, 0, 2, 1};
  43. const struct Bng_Pixel_Format RABG = {0, 3, 2, 1};
  44. const struct Bng_Pixel_Format RBAG = {0, 2, 3, 1};
  45. const struct Bng_Pixel_Format ABRG = {3, 2, 0, 1};
  46. const struct Bng_Pixel_Format BARG = {2, 3, 0, 1};
  47. const struct Bng_Pixel_Format BRAG = {2, 0, 3, 1};
  48. struct Bng_Pixel_Format_Name
  49. {
  50. char cstr[5];
  51. };
  52. struct Bng_Pixel_Format_Name name_of_pixel_format(struct Bng_Pixel_Format format)
  53. {
  54. struct Bng_Pixel_Format_Name name = {0};
  55. // BTW: if sizeof(Bng_Pixel_Format) was 1 I would not have to do these asserts, because then
  56. // the values of byte indices could not be physically equal or greater than 4.
  57. assert(format.red_byte < 4);
  58. name.cstr[format.red_byte] = 'R';
  59. assert(format.green_byte < 4);
  60. name.cstr[format.green_byte] = 'G';
  61. assert(format.blue_byte < 4);
  62. name.cstr[format.blue_byte] = 'B';
  63. assert(format.alpha_byte < 4);
  64. name.cstr[format.alpha_byte] = 'A';
  65. return name;
  66. }
  67. struct Bng_Pixel_Format pixel_format_by_name(const char *name)
  68. {
  69. struct Bng_Pixel_Format result = {0};
  70. size_t n = strlen(name);
  71. if (n > 4) n = 4;
  72. for (size_t i = 0; i < n; ++i) {
  73. switch (name[i]) {
  74. case 'R':
  75. result.red_byte = i;
  76. break;
  77. case 'G':
  78. result.green_byte = i;
  79. break;
  80. case 'B':
  81. result.blue_byte = i;
  82. break;
  83. case 'A':
  84. result.alpha_byte = i;
  85. break;
  86. default: {}
  87. }
  88. }
  89. return result;
  90. }
  91. struct RLE_Pair
  92. {
  93. uint32_t count;
  94. uint32_t pixel;
  95. };
  96. struct Bng
  97. {
  98. uint32_t magic;
  99. uint32_t width;
  100. uint32_t height;
  101. struct Bng_Pixel_Format pixel_format;
  102. uint32_t pairs_count;
  103. struct RLE_Pair pairs[];
  104. } PACKED;
  105. // NOTE: You have to allocate `width * height` amount of pixels
  106. void decompress_pixels(struct RLE_Pair *pairs, uint32_t pairs_count, uint32_t *pixels)
  107. {
  108. size_t pixels_count = 0;
  109. for (uint32_t i = 0; i < pairs_count; ++i) {
  110. for (uint32_t j = 0; j < pairs[i].count; ++j) {
  111. pixels[pixels_count++] = pairs[i].pixel;
  112. }
  113. }
  114. }
  115. // NOTE: You have to allocate `width * height` amount of pairs
  116. uint32_t compress_pixels(uint32_t width, uint32_t height, uint32_t *pixels, struct RLE_Pair *pairs)
  117. {
  118. uint32_t pairs_count = 0;
  119. const uint32_t n = width * height;
  120. for (uint32_t i = 0; i < n; ++i) {
  121. if (pairs_count > 0 && pairs[pairs_count - 1].pixel == pixels[i]) {
  122. pairs[pairs_count - 1].count += 1;
  123. } else {
  124. pairs_count += 1;
  125. pairs[pairs_count - 1].count = 1;
  126. pairs[pairs_count - 1].pixel = pixels[i];
  127. }
  128. }
  129. return pairs_count;
  130. }
  131. #define GET_BYTE(bytes, index) ((bytes & (0xFF << ((4 - index - 1) * 8))) >> ((4 - index - 1) * 8))
  132. #define SET_BYTE(bytes, index, byte) bytes = (bytes | (byte << ((4 - index - 1) * 8)))
  133. uint32_t convert_pixel(uint32_t pixel,
  134. struct Bng_Pixel_Format source,
  135. struct Bng_Pixel_Format desired)
  136. {
  137. uint32_t result = 0;
  138. SET_BYTE(result, desired.red_byte, GET_BYTE(pixel, source.red_byte));
  139. SET_BYTE(result, desired.green_byte, GET_BYTE(pixel, source.green_byte));
  140. SET_BYTE(result, desired.blue_byte, GET_BYTE(pixel, source.blue_byte));
  141. SET_BYTE(result, desired.alpha_byte, GET_BYTE(pixel, source.alpha_byte));
  142. return result;
  143. }
  144. #endif // BNG_H_