@@ -19,41 +19,18 @@
#include "common.h"
static void fill_white_holes(struct image *img);
static void find_glyphs(struct image *img);
static char *result;
/* Main function */
char *decode_xanga(struct image *img)
{
static struct font *font1 = NULL, *font2 = NULL, *font3 = NULL;
struct image *tmp;
char *result;
if(!font1)
{
font1 = font_load_variable("font_freemonobold_32_az.bmp",
"abcdefghijklmnopqrstuvwxyz");
if(!font1)
exit(1);
}
if(!font2)
{
font2 = font_load_variable("font_freemonobold_32_az.bmp",
"abcdefghijklmnopqrstuvwxyz");
if(!font2)
exit(1);
}
if(!font3)
{
font3 = font_load_variable("font_freemonobold_32_az.bmp",
"abcdefghijklmnopqrstuvwxyz");
if(!font3)
exit(1);
}
/* Xanga captchas have 7 characters */
result = malloc(8 * sizeof(char));
strcpy(result, " ");
/* Xanga captchas have 6 characters */
result = malloc(7 * sizeof(char));
strcpy(result, " ");
tmp = image_dup(img);
image_save(tmp, "xanga1.bmp");
@@ -64,20 +41,26 @@ image_save(tmp, "xanga1.bmp");
image_save(tmp, "xanga2.bmp");
fill_white_holes(tmp);
// filter_fill_holes(tmp);
filter_smooth(tmp);
//filter_median(tmp);
image_save(tmp, "xanga3.bmp");
//filter_detect_lines(tmp);
// filter_median(tmp);
//image_save(tmp, "xanga4.bmp");
filter_equalize(tmp, 128);
// filter_equalize(tmp, 128);
filter_contrast(tmp);
image_save(tmp, "xanga4.bmp");
return NULL;
#if 0
/* Detect small objects to guess image orientation */
filter_median(tmp);
filter_equalize(tmp, 200);
/* Invert rotation and find glyphs */
filter_median(tmp);
#endif
find_glyphs(tmp);
image_save(tmp, "xanga5.bmp");
/* Clean up our mess */
image_free(tmp);
@@ -130,3 +113,123 @@ static void fill_white_holes(struct image *img)
image_free(tmp);
}
static void find_glyphs(struct image *img)
{
#define FONTS 6
static struct font *fonts[FONTS];
static char *files[] =
{
"x_font_freemonobold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
"x_font_freemonobold_24_az.bmp", "abcdefghijklmnopqrstuvwxyz",
"x_font_freesansbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
//"x_font_freeserifbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
"x_font_comic_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
"x_font_comic_24_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
"x_font_freesansbold_36_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
};
struct image *tmp;
int x, y, i = 0, f;
int r, g, b;
int xmin, xmax, ymin, ymax, startx = 10, cur = 0;
int bestdist, bestfont, bestx, besty, bestch;
for(f = 0; f < FONTS; f++)
{
if(!fonts[f])
{
fonts[f] = font_load_variable(files[f * 2], files[f * 2 + 1]);
if(!fonts[f])
exit(1);
//filter_smooth(fonts[f]->img);
//filter_contrast(fonts[f]->img);
}
}
tmp = image_new(img->width, img->height);
for(y = 0; y < img->height; y++)
for(x = 0; x < img->width; x++)
{
getpixel(img, x, y, &r, &g, &b);
setpixel(tmp, x, y, 255, g, 255);
}
while(cur < 6)
{
/* Try to find 1st letter */
bestdist = INT_MAX;
for(f = 0; f < FONTS; f++) for(i = 0; i < fonts[f]->size; i++)
{
int localmin = INT_MAX, localx, localy;
int sqr;
if(fonts[f]->glyphs[i].c == 'l' || fonts[f]->glyphs[i].c == 'z')
continue;
xmin = fonts[f]->glyphs[i].xmin - 5;
ymin = fonts[f]->glyphs[i].ymin - 3;
xmax = fonts[f]->glyphs[i].xmax + 5;
ymax = fonts[f]->glyphs[i].ymax + 3;
sqr = sqrt(xmax - xmin);
for(y = -15; y < 15; y++)
//for(x = startx; x < startx + 15; x++)
for(x = 22 - (xmax - xmin) / 2 + 25 * cur; x < 28 - (xmax - xmin) / 2 + 25 * cur; x++)
{
int z, t, dist;
dist = 0;
for(t = 0; t < ymax - ymin; t++)
for(z = 0; z < xmax - xmin; z++)
{
int r2;
getgray(fonts[f]->img, xmin + z, ymin + t, &r);
getgray(img, x + z, y + t, &r2);
if(r < r2)
dist += (r - r2) * (r - r2);
else
dist += (r - r2) * (r - r2) * 3 / 4;
}
// printf("%i %i -> %i\n", x, y, dist);
// dist /= (xmax - xmin);
// dist = dist / sqrt((ymax - ymin) * (xmax - xmin)) / (xmax - xmin);
dist = dist / (xmax - xmin) / sqr;
// dist = dist * 128 / fonts[f]->glyphs[i].count;
if(dist < localmin)
{
localmin = dist;
localx = x;
localy = y;
}
}
//fprintf(stderr, "%i (%i,%i)\n", localmin, localx - startx, localy);
if(localmin < bestdist)
{
//printf(" bestch is now %i (%c) in font %i\n", i, fonts[f]->glyphs[i].c, f);
bestdist = localmin;
bestfont = f;
bestx = localx;
besty = localy;
bestch = i;
}
}
//printf("%i (%c) in font %i\n", i, fonts[bestfont]->glyphs[bestch].c, bestfont);
//printf("%i < %i < %i\n", 10 + 25 * cur, bestx, 30 + 25 * cur);
/* Draw best glyph in picture (debugging purposes) */
xmin = fonts[bestfont]->glyphs[bestch].xmin - 5;
ymin = fonts[bestfont]->glyphs[bestch].ymin - 3;
xmax = fonts[bestfont]->glyphs[bestch].xmax + 5;
ymax = fonts[bestfont]->glyphs[bestch].ymax + 3;
for(y = 0; y < ymax - ymin; y++)
for(x = 0; x < xmax - xmin; x++)
{
getpixel(fonts[bestfont]->img, xmin + x, ymin + y, &r, &g, &b);
if(r > 128) continue;
setpixel(tmp, bestx + x, besty + y, r, g, b);
}
startx = bestx + xmax - xmin;
result[cur++] = fonts[bestfont]->glyphs[bestch].c;
}
image_swap(img, tmp);
image_free(tmp);
}