You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

265 line
6.6 KiB

  1. /*
  2. * sortchars analyse ASCII characters
  3. * Copyright (c) 2007 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. #include "config.h"
  15. #if !defined(__KERNEL__)
  16. # include <stdio.h>
  17. # include <string.h>
  18. # include <stdlib.h>
  19. #endif
  20. #include "caca.h"
  21. #define GLYPHS 0x7f
  22. #define FONT 0 /* 0 or 1 */
  23. #define DX 2
  24. #define DY 3
  25. #define RANGEBITS 2
  26. #define RANGE (1 << RANGEBITS)
  27. #define FULLRANGE (1 << (RANGEBITS * DX * DY))
  28. int total[GLYPHS][DX][DY];
  29. int16_t allbits[GLYPHS];
  30. int bestchar[FULLRANGE];
  31. static int curve[17] = /* 17 instead of 16 */
  32. {
  33. 0, 4, 6, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15
  34. //0, 3, 5, 7, 8, 9, 10, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15
  35. //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15
  36. };
  37. static int distance(uint16_t, uint16_t);
  38. static void testcircle(void);
  39. int main(int argc, char *argv[])
  40. {
  41. int count[DX][DY];
  42. char utf8[7];
  43. caca_canvas_t *cv;
  44. caca_font_t *f;
  45. char const * const * fonts;
  46. uint8_t *img;
  47. unsigned int w, h, x, y;
  48. int ret, i, max;
  49. /* Load a libcaca internal font */
  50. fonts = caca_get_font_list();
  51. if(fonts[FONT] == NULL)
  52. {
  53. fprintf(stderr, "error: libcaca was compiled without any fonts\n");
  54. return -1;
  55. }
  56. f = caca_load_font(fonts[FONT], 0);
  57. if(f == NULL)
  58. {
  59. fprintf(stderr, "error: could not load font \"%s\"\n", fonts[0]);
  60. return -1;
  61. }
  62. cv = caca_create_canvas(1, 1);
  63. caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK);
  64. /* Create our bitmap buffer (32-bit ARGB) */
  65. w = caca_get_font_width(f);
  66. h = caca_get_font_height(f);
  67. img = malloc(4 * w * h);
  68. /* Zero our structures */
  69. for(y = 0; y < DY; y++)
  70. for(x = 0; x < DX; x++)
  71. count[x][y] = 0;
  72. for(y = 0; y < h; y++)
  73. for(x = 0; x < w; x++)
  74. count[x * DX / w][y * DY / h]++;
  75. for(i = 0x20; i < GLYPHS; i++)
  76. for(y = 0; y < DY; y++)
  77. for(x = 0; x < DX; x++)
  78. total[i][x][y] = 0;
  79. /* Draw all glyphs and count their pixels */
  80. for(i = 0x20; i < GLYPHS; i++)
  81. {
  82. caca_put_char(cv, 0, 0, i);
  83. /* Render the canvas onto our image buffer */
  84. caca_render_canvas(cv, f, img, w, h, 4 * w);
  85. for(y = 0; y < h * DY; y++)
  86. for(x = 0; x < w * DX; x++)
  87. total[i][x / w][y / h]
  88. += img[(w * (y / DY) + (x / DX)) * 4 + 1];
  89. }
  90. /* Compute max pixel value */
  91. max = 0;
  92. for(i = 0x20; i < GLYPHS; i++)
  93. for(y = 0; y < DY; y++)
  94. for(x = 0; x < DX; x++)
  95. {
  96. int val = total[i][x][y] * 256 / count[x][y];
  97. if(val > max)
  98. max = val;
  99. }
  100. /* Compute bits for all glyphs */
  101. for(i = 0x20; i < GLYPHS; i++)
  102. {
  103. int bits = 0;
  104. if(i >= 0x7f && i <= 0x9f)
  105. {
  106. allbits[i] = 0;
  107. continue;
  108. }
  109. for(y = 0; y < DY; y++)
  110. {
  111. for(x = 0; x < DX; x++)
  112. {
  113. int t = total[i][x][y] * 16 * 256 / (count[x][y] * max);
  114. bits *= RANGE;
  115. bits |= curve[t] / (16 / RANGE);
  116. }
  117. }
  118. allbits[i] = bits;
  119. }
  120. /* Find a glyph for all combinations */
  121. for(i = 0; i < FULLRANGE; i++)
  122. {
  123. int j, mindist = 0x1000, best = 0;
  124. for(j = 0x20; j < GLYPHS; j++)
  125. {
  126. int d = distance(i, allbits[j]);
  127. if(d < mindist)
  128. {
  129. best = j;
  130. mindist = d;
  131. if(d == 0)
  132. break;
  133. }
  134. }
  135. bestchar[i] = best;
  136. }
  137. /* Print results */
  138. printf("/* Generated by sortchars.c */\n");
  139. printf("static char const cells_to_ascii[%i] =\n{\n ", FULLRANGE);
  140. for(i = 0; i < FULLRANGE; i++)
  141. {
  142. ret = caca_utf32_to_utf8(utf8, bestchar[i]);
  143. utf8[ret] = '\0';
  144. printf("%i, ", bestchar[i]);
  145. if((i % 16) == 15 && i != FULLRANGE - 1)
  146. printf("\n ");
  147. }
  148. printf("\n};\n\n");
  149. printf("static uint16_t const ascii_to_cells[%i] =\n{\n ", GLYPHS);
  150. for(i = 0; i < GLYPHS; i++)
  151. {
  152. ret = caca_utf32_to_utf8(utf8, bestchar[i]);
  153. utf8[ret] = '\0';
  154. printf("0x%03x, ", allbits[i]);
  155. if((i % 8) == 7 && i != GLYPHS - 1)
  156. printf("\n ");
  157. }
  158. printf("\n};\n");
  159. caca_free_canvas(cv);
  160. testcircle();
  161. return 0;
  162. }
  163. static int distance(uint16_t mychar, uint16_t x)
  164. {
  165. int i, d = 0;
  166. for(i = 0; i < DX * DY; i++)
  167. {
  168. int t = (int)(mychar & (RANGE - 1)) - (int)(x & (RANGE - 1));
  169. d += t > 0 ? 1 * t : -2 * t;
  170. mychar /= RANGE;
  171. x /= RANGE;
  172. }
  173. return d;
  174. }
  175. #define WIDTH 40
  176. #define HEIGHT 18
  177. static void testcircle(void)
  178. {
  179. char utf8[7];
  180. uint8_t *buf = malloc(256 * 256);
  181. uint16_t *dst = malloc(WIDTH * DX * HEIGHT * DY * sizeof(uint16_t));
  182. int x, y, ret;
  183. memset(buf, 0, 256 * 256);
  184. memset(dst, 0, WIDTH * DX * HEIGHT * DY);
  185. /* Fill image */
  186. for(y = 0; y < 256; y++)
  187. for(x = 0; x < 256; x++)
  188. {
  189. int dist2 = (x - 128) * (x - 128) + (y - 128) * (y - 128);
  190. if(dist2 < 25000 && dist2 > 18000)
  191. buf[y * 256 + x] = 255;
  192. else if(dist2 < 14000 && dist2 > 9000)
  193. buf[y * 256 + x] = 204;
  194. else if(dist2 < 6000 && dist2 > 3000)
  195. buf[y * 256 + x] = 153;
  196. else if(dist2 < 1600 && dist2 > 300)
  197. buf[y * 256 + x] = 102;
  198. }
  199. /* Parse image */
  200. for(y = 0; y < HEIGHT * DY; y++)
  201. for(x = 0; x < WIDTH * DX; x++)
  202. dst[y * WIDTH * DX + x] = (int)buf[(y * 256 / (HEIGHT * DY)) * 256 + (x * 256 / (WIDTH * DX))] * RANGE / 256;
  203. printf("/* example:\n");
  204. for(y = 0; y < HEIGHT; y++)
  205. {
  206. for(x = 0; x < WIDTH; x++)
  207. {
  208. uint16_t bits = 0;
  209. int i, j;
  210. for(j = 0; j < DY; j++)
  211. for(i = 0; i < DX; i++)
  212. {
  213. bits *= RANGE;
  214. bits |= dst[(y * DY + j) * WIDTH * DX + x * DX + i];
  215. }
  216. ret = caca_utf32_to_utf8(utf8, bestchar[bits]);
  217. utf8[ret] = '\0';
  218. printf("%s", utf8);
  219. }
  220. printf("\n");
  221. }
  222. printf("*/\n");
  223. }