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.
 
 
 
 
 
 

147 lines
3.7 KiB

  1. /*
  2. * vbulletin.c: decode vbulletin captchas
  3. * $Id$
  4. *
  5. * Copyright: (c) 2005 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 <limits.h>
  15. #include "config.h"
  16. #include "common.h"
  17. #define FONTNAME "font_vbulletin.png"
  18. static struct image *font = NULL;
  19. /* Main function */
  20. char *decode_vbulletin(struct image *img)
  21. {
  22. char all[] = "2346789ABCDEFGHJKLMNPRTWXYZ";
  23. char *result;
  24. struct image *tmp1, *tmp2, *tmp3;
  25. int limits[6] = { 26, 53, 80, 107, 134, 160 };
  26. int x, y, r, g, b, i, j;
  27. if(!font)
  28. {
  29. char fontname[BUFSIZ];
  30. sprintf(fontname, "%s/%s", share, FONTNAME);
  31. font = image_load(fontname);
  32. if(!font)
  33. {
  34. fprintf(stderr, "cannot load font %s\n", fontname);
  35. exit(-1);
  36. }
  37. }
  38. /* vBulletin captchas have 6 characters */
  39. result = malloc(7 * sizeof(char));
  40. strcpy(result, " ");
  41. /* half the captchas are inverse video; we set them back to normal */
  42. getpixel(img, 0, 0, &r, &g, &b);
  43. if(r < 50)
  44. tmp1 = filter_equalize(img, 128);
  45. else
  46. tmp1 = filter_equalize(img, -128);
  47. /* Remove garbage around the cells */
  48. for(x = 0; x < img->width; x++)
  49. {
  50. for(y = 0; y < 15; y++)
  51. setpixel(tmp1, x, y, 255, 255, 255);
  52. for(y = 45; y < img->height; y++)
  53. setpixel(tmp1, x, y, 255, 255, 255);
  54. }
  55. for(x = 0; x < img->width; x++)
  56. {
  57. for(i = 0; i < 6; i++)
  58. if(x == limits[i])
  59. break;
  60. if(i == 6)
  61. for(y = 15; y < 45; y++)
  62. setpixel(tmp1, x, y, 255, 255, 255);
  63. else
  64. x += 11;
  65. }
  66. tmp2 = filter_black_stuff(tmp1);
  67. tmp3 = filter_black_stuff(tmp2);
  68. /* Fill letters in gray */
  69. for(x = 26; x < 172; x++)
  70. {
  71. getpixel(tmp3, x, 15, &r, &g, &b);
  72. if(r == 0)
  73. filter_flood_fill(tmp3, x, 15, 127, 0, 255);
  74. }
  75. /* Find remaining black parts and remove them */
  76. for(x = 26; x < 172; x++)
  77. for(y = 15; y < 45; y++)
  78. {
  79. getpixel(tmp3, x, y, &r, &g, &b);
  80. if(r == 0)
  81. filter_flood_fill(tmp3, x, y, 255, 255, 255);
  82. }
  83. /* Fill letters in black */
  84. for(x = 26; x < 172; x++)
  85. {
  86. getpixel(tmp3, x, 44, &r, &g, &b);
  87. if(r == 127)
  88. filter_flood_fill(tmp3, x, 44, 0, 0, 0);
  89. }
  90. /* Find remaining gray parts and remove them */
  91. for(x = 26; x < 172; x++)
  92. for(y = 15; y < 45; y++)
  93. {
  94. getpixel(tmp3, x, y, &r, &g, &b);
  95. if(r == 127)
  96. filter_flood_fill(tmp3, x, y, 255, 255, 255);
  97. }
  98. /* Guess all glyphs */
  99. for(i = 0; i < 6; i++)
  100. {
  101. struct image *new;
  102. int mindist = INT_MAX, min = -1;
  103. new = filter_crop(tmp3, limits[i], 15, limits[i] + 11, 45);
  104. for(j = 0; j < 27; j++)
  105. {
  106. int dist = 0;
  107. for(y = 0; y < new->height; y++)
  108. for(x = 0; x < new->width; x++)
  109. {
  110. int r2, g2, b2;
  111. getpixel(font, 12 * j + x, y, &r, &g, &b);
  112. getpixel(new, x, y, &r2, &g2, &b2);
  113. dist += (r - r2) * (r - r2);
  114. }
  115. if(dist < mindist)
  116. {
  117. mindist = dist;
  118. min = j;
  119. }
  120. }
  121. image_free(new);
  122. result[i] = all[min];
  123. }
  124. image_free(tmp1);
  125. image_free(tmp2);
  126. image_free(tmp3);
  127. return result;
  128. }