25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

197 lines
4.7 KiB

  1. /*
  2. * scode.c: decode scode captchas
  3. * $Id$
  4. *
  5. * Copyright: (c) 2004 Sam Hocevar <sam@zoy.org>
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License as published by Banlu Kemiyatorn. See
  9. * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "config.h"
  15. #include "common.h"
  16. static char find_glyph(struct image *img, int xmin, int xmax);
  17. /* Main function */
  18. char *decode_scode(struct image *img)
  19. {
  20. char *result;
  21. int stats[3 * 256];
  22. int x, y, i, incell = 0, cur = 0, xmin = 0;
  23. int r, g, b;
  24. struct image *tmp1;
  25. /* allocate enough place */
  26. result = malloc(1024 * sizeof(char));
  27. tmp1 = image_dup(img);
  28. /* Remove border */
  29. getpixel(img, 1, 1, &r, &g, &b);
  30. for(y = 0; y < img->height; y++)
  31. {
  32. setpixel(tmp1, 0, y, r, g, b);
  33. setpixel(tmp1, img->width - 1, y, r, g, b);
  34. }
  35. for(x = 0; x < img->width; x++)
  36. {
  37. setpixel(tmp1, x, 0, r, g, b);
  38. setpixel(tmp1, x, img->height - 1, r, g, b);
  39. }
  40. /* Detect background: first and last 3 lines */
  41. for(i = 0; i < 3 * 256; i++)
  42. stats[i] = 0;
  43. for(y = 0; y < 3; y++)
  44. for(x = 0; x < img->width; x++)
  45. {
  46. getpixel(tmp1, x, y, &r, &g, &b);
  47. stats[r + g + b]++;
  48. getpixel(tmp1, x, img->height - 1 - y, &r, &g, &b);
  49. stats[r + g + b]++;
  50. }
  51. /* Set non-background colours to 0 */
  52. for(y = 0; y < img->height; y++)
  53. for(x = 0; x < img->width; x++)
  54. {
  55. getpixel(tmp1, x, y, &r, &g, &b);
  56. if(stats[r + g + b])
  57. setpixel(tmp1, x, y, 255, 255, 255);
  58. else
  59. setpixel(tmp1, x, y, 0, 0, 0);
  60. }
  61. /* Decode glyphs */
  62. for(x = 0; x < img->width; x++)
  63. {
  64. int found = 0;
  65. for(y = 0; y < img->height; y++)
  66. {
  67. getpixel(tmp1, x, y, &r, &g, &b);
  68. if(!r)
  69. {
  70. found = 1;
  71. break;
  72. }
  73. }
  74. if(found && !incell)
  75. {
  76. incell = 1;
  77. xmin = x;
  78. }
  79. else if(!found && incell)
  80. {
  81. incell = 0;
  82. /* Find glyph */
  83. result[cur++] = find_glyph(tmp1, xmin, x);
  84. }
  85. }
  86. image_free(tmp1);
  87. result[cur] = '\0';
  88. return result;
  89. }
  90. static char find_glyph(struct image *img, int xmin, int xmax)
  91. {
  92. int ymin = -1, ymax = -1;
  93. int x, y, count = 0;
  94. int r, g, b;
  95. /* Compute vertical bounds of glyph */
  96. for(y = 0; y < img->height; y++)
  97. {
  98. int found = 0;
  99. for(x = xmin; x < xmax; x++)
  100. {
  101. getpixel(img, x, y, &r, &g, &b);
  102. if(!r)
  103. {
  104. found = 1;
  105. break;
  106. }
  107. }
  108. if(found)
  109. {
  110. if(ymin == -1)
  111. ymin = y;
  112. else
  113. ymax = y + 1;
  114. }
  115. }
  116. for(x = xmin; x < xmax; x++)
  117. {
  118. for(y = ymin; y < ymax; y++)
  119. {
  120. getpixel(img, x, y, &r, &g, &b);
  121. if(!r)
  122. count += 5 * (y - ymin) ^ 3 * (x - xmin);
  123. //count += y - ymin;
  124. }
  125. }
  126. switch(count)
  127. {
  128. /* Scode font */
  129. case 778: return '0';
  130. case 621: return '1';
  131. case 854: return '2';
  132. case 784: return '3';
  133. case 766: return '4';
  134. case 771: return '5';
  135. case 976: return '6';
  136. case 585: return '7';
  137. case 980: return '8';
  138. case 896: return '9';
  139. /* Small font */
  140. case 584: return '0';
  141. case 454: return '1';
  142. case 517: return '2';
  143. case 447: return '3';
  144. case 469: return '4';
  145. case 472: return '5';
  146. case 564: return '6';
  147. case 298: return '7';
  148. case 560: return '8';
  149. case 536: return '9';
  150. /* Thin font */
  151. case 438: return '0';
  152. case 405: return '1';
  153. case 485: return '2';
  154. case 486: return '3';
  155. case 413: return '4';
  156. case 509: return '5';
  157. case 582: return '6';
  158. case 242: return '7';
  159. case 579: return '8';
  160. case 440: return '9';
  161. #if 0
  162. case 162: return '0';
  163. case 131: return '1';
  164. case 150: return '2';
  165. case 139: return '3';
  166. case 155: return '4';
  167. case 159: return '5';
  168. case 181: return '6';
  169. case 90: return '7';
  170. case 180: return '8';
  171. case 170: return '9';
  172. #endif
  173. default:
  174. dprintf("don't know about checksum %i\n", count);
  175. return '?';
  176. }
  177. }