_convert.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. int main(int argc, char* argv[]) {
  6. const unsigned char* pp = NULL;
  7. uint32_t pix = 0;
  8. int bit = 0;
  9. uint8_t b = 0;
  10. uint8_t bcnt = 0;
  11. unsigned int lcnt = 0;
  12. static const int lmax = 16; // max hex values per line
  13. uint8_t* buf = NULL;
  14. uint8_t* bp = NULL;
  15. unsigned int blen = 0;
  16. uint8_t* cmp = NULL;
  17. uint8_t* cp = NULL;
  18. unsigned int clen = 0;
  19. uint8_t ctag = 0xFF;
  20. uint32_t tag[256] = {0};
  21. uint32_t tmax = UINT32_MAX;
  22. unsigned int x, y, z;
  23. const char* name = argv[1];
  24. FILE* fh = fopen(argv[2], "wb");
  25. uint32_t white = 0xFF;
  26. int rv = 0; // assume success
  27. // allocate buffers
  28. blen = ((img.w * img.h) + 0x7) >> 3;
  29. bp = (buf = calloc(blen + 1, 1));
  30. cp = (cmp = calloc(blen + 4, 1));
  31. // sanity check
  32. if(!fh || !buf || !cmp) {
  33. printf("! fopen() or malloc() fail.\n");
  34. rv = 255;
  35. goto bail;
  36. }
  37. // Find white value
  38. for(x = 1; x < img.bpp; x++)
  39. white = (white << 8) | 0xFF;
  40. // build bit pattern
  41. // create the comment as we go
  42. for(pp = img.b, y = 0; y < img.h; y++) {
  43. fprintf(fh, "// ");
  44. for(x = 0; x < img.w; x++) {
  45. // read pixel
  46. for(pix = 0, z = 0; z < img.bpp; pix = (pix << 8) | *pp++, z++)
  47. ;
  48. // get bit and draw
  49. if(pix < white) {
  50. b = (b << 1) | 1;
  51. fprintf(fh, "##");
  52. } else {
  53. b <<= 1;
  54. fprintf(fh, "..");
  55. }
  56. // got byte
  57. if((++bcnt) == 8) {
  58. *bp++ = b;
  59. tag[b]++;
  60. bcnt = (b = 0);
  61. }
  62. }
  63. fprintf(fh, "\n");
  64. }
  65. fprintf(fh, "\n");
  66. // padding
  67. if(bcnt) {
  68. b <<= (bcnt = 8 - bcnt);
  69. *bp++ = b;
  70. tag[b]++;
  71. }
  72. // Kill the compression
  73. *bp = ~bp[-1]; // https://youtube.com/clip/Ugkx-JZIr16hETy7hz_H6yIdKPtxVe8C5w_V
  74. // Byte run length compression
  75. // Find a good tag
  76. for(x = 0; tmax && (x < 256); x++) {
  77. if(tag[x] < tmax) {
  78. tmax = tag[x];
  79. ctag = x;
  80. }
  81. }
  82. // compress the data
  83. for(bp = buf, x = 0; (clen < blen) && (x < blen); x++) {
  84. // need at least 4 the same to be worth it
  85. // must compress tag (if it occurs)
  86. if((bp[x] == bp[x + 1]) && (bp[x] == bp[x + 2]) && (bp[x] == bp[x + 3]) ||
  87. (bp[x] == ctag)) {
  88. for(y = 1; (y < 255) && (bp[x] == bp[x + y]); y++)
  89. ;
  90. *cp++ = ctag; // tag
  91. *cp++ = y; // length
  92. *cp++ = bp[x]; // byte
  93. x += y - 1;
  94. clen += 3;
  95. } else {
  96. *cp++ = bp[x];
  97. clen++;
  98. }
  99. }
  100. // create struct
  101. fprintf(fh, "#include \"images.h\"\n\n");
  102. fprintf(fh, "const image_t img_%s = { %d, %d, ", name, img.w, img.h);
  103. if(clen < blen) { // dump compressed?
  104. fprintf(
  105. fh,
  106. "true, %d, 0x%02X, { // orig:%d, comp:%.2f%%\n\t",
  107. clen,
  108. ctag,
  109. blen,
  110. 100.0 - ((clen * 100.0) / blen));
  111. for(x = 0; x < clen; x++)
  112. if(x == clen - 1)
  113. fprintf(fh, "0x%02X\n}};\n", cmp[x]);
  114. else
  115. fprintf(fh, "0x%02X%s", cmp[x], (!((x + 1) % 16)) ? ",\n\t" : ", ");
  116. } else { // dump UNcompressed
  117. fprintf(fh, "false, %d, 0, {\n\t", blen);
  118. for(x = 0; x < blen; x++)
  119. if(x == blen - 1)
  120. fprintf(fh, "0x%02X\n}};\n", buf[x]);
  121. else
  122. fprintf(fh, "0x%02X%s", buf[x], (!((x + 1) % 16)) ? ",\n\t" : ", ");
  123. }
  124. bail:
  125. if(fh) fclose(fh);
  126. if(buf) free(buf);
  127. if(cmp) free(cmp);
  128. return rv;
  129. }