選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

264 行
6.6 KiB

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