/* * phpbb.c: decode phpBB captchas * $Id$ * * Copyright: (c) 2005 Sam Hocevar * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://sam.zoy.org/wtfpl/COPYING for more details. */ #include #include #include #include #include "config.h" #include "common.h" /* Main function */ char *decode_phpbb(struct image *img) { static struct font *font = NULL; char *result; struct image *tmp1, *tmp2; int x, y, i = 0; int r, g, b; int xmin, xmax, ymin, ymax, cur, offset = -1; int distmin, distx, disty, distch; if(!font) { font = font_load_fixed("font_phpbb.png", "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"); if(!font) exit(-1); } /* phpBB captchas have 6 characters */ result = malloc(7 * sizeof(char)); strcpy(result, " "); tmp1 = image_dup(img); tmp2 = image_new(img->width, img->height); filter_smooth(tmp1); filter_threshold(tmp1, 128); for(x = 0; x < img->width; x++) for(y = 0; y < img->height; y++) { getpixel(tmp1, x, y, &r, &g, &b); if(r == 0 && offset == -1) offset = x; getpixel(img, x, y, &r, &g, &b); setpixel(tmp2, x, y, 255, g, 255); } for(cur = 0; cur < 6; cur++) { /* Try to find 1st letter */ distmin = INT_MAX; for(i = 0; i < font->size; i++) { int localmin = INT_MAX, localx, localy; xmin = font->glyphs[i].xmin; ymin = font->glyphs[i].ymin; xmax = font->glyphs[i].xmax; ymax = font->glyphs[i].ymax; for(y = 0; y < img->height - (ymax - ymin); y++) { x = offset - 3; if(cur == 0) x -= 10; if(x < 0) x = 0; for(; x < offset + 3; x++) { int z, t, dist; dist = 0; for(t = 0; t < ymax - ymin; t++) for(z = 0; z < xmax - xmin; z++) { int r2; getgray(font->img, xmin + z, ymin + t, &r); getgray(tmp1, x + z, y + t, &r2); if(r > r2) dist += r - r2; else dist += (r2 - r) * 3 / 4; } if(dist < localmin) { localmin = dist; localx = x; localy = y; } } } if(localmin < distmin) { distmin = localmin; distx = localx; disty = localy; distch = i; } } /* Print min glyph (debug) */ xmin = font->glyphs[distch].xmin; ymin = font->glyphs[distch].ymin; xmax = font->glyphs[distch].xmax; ymax = font->glyphs[distch].ymax; for(y = 0; y < ymax - ymin; y++) for(x = 0; x < xmax - xmin; x++) { int r2; getpixel(font->img, xmin + x, ymin + y, &r2, &g, &b); if(r2 > 128) continue; getpixel(tmp2, distx + x, disty + y, &r, &g, &b); setpixel(tmp2, distx + x, disty + y, r2, g, b); } offset = distx + xmax - xmin; result[cur] = font->glyphs[distch].c; } image_free(tmp1); image_free(tmp2); return result; }