diff --git a/share/font_comic_24_az_messed.bmp b/share/font_comic_24_az_messed.bmp new file mode 100644 index 0000000..50915dd Binary files /dev/null and b/share/font_comic_24_az_messed.bmp differ diff --git a/share/font_comic_32_az.bmp b/share/font_comic_32_az.bmp new file mode 100644 index 0000000..def41f5 Binary files /dev/null and b/share/font_comic_32_az.bmp differ diff --git a/share/font_freemonobold_24_az.bmp b/share/font_freemonobold_24_az.bmp new file mode 100644 index 0000000..09df251 Binary files /dev/null and b/share/font_freemonobold_24_az.bmp differ diff --git a/share/font_freemonobold_32_az.bmp b/share/font_freemonobold_32_az.bmp new file mode 100644 index 0000000..389ec78 Binary files /dev/null and b/share/font_freemonobold_32_az.bmp differ diff --git a/share/font_freesansbold_32_az.bmp b/share/font_freesansbold_32_az.bmp new file mode 100644 index 0000000..a763988 Binary files /dev/null and b/share/font_freesansbold_32_az.bmp differ diff --git a/share/font_freesansbold_36_az_messed.bmp b/share/font_freesansbold_36_az_messed.bmp new file mode 100644 index 0000000..446fa98 Binary files /dev/null and b/share/font_freesansbold_36_az_messed.bmp differ diff --git a/share/x_font_comic_24_az_messed.bmp b/share/x_font_comic_24_az_messed.bmp new file mode 100644 index 0000000..1be8fe0 Binary files /dev/null and b/share/x_font_comic_24_az_messed.bmp differ diff --git a/share/x_font_comic_32_az.bmp b/share/x_font_comic_32_az.bmp new file mode 100644 index 0000000..d78244d Binary files /dev/null and b/share/x_font_comic_32_az.bmp differ diff --git a/share/x_font_freemonobold_24_az.bmp b/share/x_font_freemonobold_24_az.bmp new file mode 100644 index 0000000..1d549cc Binary files /dev/null and b/share/x_font_freemonobold_24_az.bmp differ diff --git a/share/x_font_freemonobold_32_az.bmp b/share/x_font_freemonobold_32_az.bmp new file mode 100644 index 0000000..ea0e0c5 Binary files /dev/null and b/share/x_font_freemonobold_32_az.bmp differ diff --git a/share/x_font_freesansbold_32_az.bmp b/share/x_font_freesansbold_32_az.bmp new file mode 100644 index 0000000..2335e11 Binary files /dev/null and b/share/x_font_freesansbold_32_az.bmp differ diff --git a/share/x_font_freesansbold_36_az_messed.bmp b/share/x_font_freesansbold_36_az_messed.bmp new file mode 100644 index 0000000..a2b2f93 Binary files /dev/null and b/share/x_font_freesansbold_36_az_messed.bmp differ diff --git a/src/main.c b/src/main.c index 6f75246..51d6065 100644 --- a/src/main.c +++ b/src/main.c @@ -209,6 +209,7 @@ int main(int argc, char *argv[]) } printf("%s\n", result); + fflush(stdout); free(result); } diff --git a/src/xanga.c b/src/xanga.c index cd3ced2..61a915e 100644 --- a/src/xanga.c +++ b/src/xanga.c @@ -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); +} +