|
- /*
- * vbulletin.c: decode vbulletin captchas
- * $Id$
- *
- * Copyright: (c) 2005 Sam Hocevar <sam@zoy.org>
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the Do What The Fuck You Want To
- * Public License as published by Banlu Kemiyatorn. See
- * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
-
- #include "config.h"
- #include "common.h"
-
- #define FONTNAME "font_vbulletin.png"
- static struct image *font = NULL;
-
- /* Main function */
- char *decode_vbulletin(struct image *img)
- {
- char all[] = "2346789ABCDEFGHJKLMNPRTWXYZ";
- char *result;
- struct image *tmp1, *tmp2, *tmp3;
- int limits[6] = { 26, 53, 80, 107, 134, 160 };
- int x, y, r, g, b, i, j;
-
- if(!font)
- {
- char fontname[BUFSIZ];
- sprintf(fontname, "%s/%s", share, FONTNAME);
- font = image_load(fontname);
- if(!font)
- {
- fprintf(stderr, "cannot load font %s\n", fontname);
- exit(-1);
- }
- }
-
- /* vBulletin captchas have 6 characters */
- result = malloc(7 * sizeof(char));
- strcpy(result, " ");
-
- /* half the captchas are inverse video; we set them back to normal */
- getpixel(img, 0, 0, &r, &g, &b);
- if(r < 50)
- tmp1 = filter_equalize(img, 128);
- else
- tmp1 = filter_equalize(img, -128);
-
- /* Remove garbage around the cells */
- for(x = 0; x < img->width; x++)
- {
- for(y = 0; y < 15; y++)
- setpixel(tmp1, x, y, 255, 255, 255);
- for(y = 45; y < img->height; y++)
- setpixel(tmp1, x, y, 255, 255, 255);
- }
-
- for(x = 0; x < img->width; x++)
- {
- for(i = 0; i < 6; i++)
- if(x == limits[i])
- break;
- if(i == 6)
- for(y = 15; y < 45; y++)
- setpixel(tmp1, x, y, 255, 255, 255);
- else
- x += 11;
- }
-
- tmp2 = filter_black_stuff(tmp1);
- tmp3 = filter_black_stuff(tmp2);
-
- /* Fill letters in gray */
- for(x = 26; x < 172; x++)
- {
- getpixel(tmp3, x, 15, &r, &g, &b);
- if(r == 0)
- filter_flood_fill(tmp3, x, 15, 127, 0, 255);
- }
-
- /* Find remaining black parts and remove them */
- for(x = 26; x < 172; x++)
- for(y = 15; y < 45; y++)
- {
- getpixel(tmp3, x, y, &r, &g, &b);
- if(r == 0)
- filter_flood_fill(tmp3, x, y, 255, 255, 255);
- }
-
- /* Fill letters in black */
- for(x = 26; x < 172; x++)
- {
- getpixel(tmp3, x, 44, &r, &g, &b);
- if(r == 127)
- filter_flood_fill(tmp3, x, 44, 0, 0, 0);
- }
-
- /* Find remaining gray parts and remove them */
- for(x = 26; x < 172; x++)
- for(y = 15; y < 45; y++)
- {
- getpixel(tmp3, x, y, &r, &g, &b);
- if(r == 127)
- filter_flood_fill(tmp3, x, y, 255, 255, 255);
- }
-
- /* Guess all glyphs */
- for(i = 0; i < 6; i++)
- {
- struct image *new;
- int mindist = INT_MAX, min = -1;
- new = filter_crop(tmp3, limits[i], 15, limits[i] + 11, 45);
- for(j = 0; j < 27; j++)
- {
- int dist = 0;
- for(y = 0; y < new->height; y++)
- for(x = 0; x < new->width; x++)
- {
- int r2, g2, b2;
- getpixel(font, 12 * j + x, y, &r, &g, &b);
- getpixel(new, x, y, &r2, &g2, &b2);
- dist += (r - r2) * (r - r2);
- }
- if(dist < mindist)
- {
- mindist = dist;
- min = j;
- }
- }
- image_free(new);
- result[i] = all[min];
- }
-
- image_free(tmp1);
- image_free(tmp2);
- image_free(tmp3);
-
- return result;
- }
|