git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/pwntcha/trunk@448 92316355-f0b4-4df1-b90c-862c8a59935fmaster
| @@ -3,8 +3,9 @@ NULL = | |||
| bin_PROGRAMS = pwntcha | |||
| pwntcha_SOURCES = \ | |||
| main.c \ | |||
| filter.c \ | |||
| font.c \ | |||
| image.c \ | |||
| filters.c \ | |||
| common.h \ | |||
| authimage.c \ | |||
| clubic.c \ | |||
| @@ -18,44 +18,38 @@ | |||
| #include "config.h" | |||
| #include "common.h" | |||
| #define FONTNAME "font_authimage.png" | |||
| static struct image *font = NULL; | |||
| /* Main function */ | |||
| char *decode_authimage(struct image *img) | |||
| { | |||
| char *all = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |||
| static struct font *font = NULL; | |||
| char *result; | |||
| struct image *tmp; | |||
| int x, y, r, g, b, i; | |||
| if(!font) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| sprintf(fontname, "%s/%s", share, FONTNAME); | |||
| font = image_load(fontname); | |||
| font = font_load_fixed("font_authimage.png", | |||
| "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); | |||
| if(!font) | |||
| { | |||
| fprintf(stderr, "cannot load font %s\n", fontname); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* authimage captchas have 6 characters */ | |||
| result = malloc(7 * sizeof(char)); | |||
| memset(result, '\0', 7); | |||
| /* half the captchas are inverse video; we set them back to normal */ | |||
| /* double the captcha size for better accuracy in the rotation */ | |||
| tmp = image_dup(img); | |||
| filter_scale(tmp, 2.0); | |||
| getpixel(tmp, 0, 0, &r, &g, &b); | |||
| filter_equalize(tmp, r * 3 / 4); | |||
| filter_smooth(tmp); | |||
| filter_equalize(tmp, 220); | |||
| for(i = 0; i < 6; i++) | |||
| { | |||
| int mindiff = INT_MAX, minch = -1, ch; | |||
| for(ch = 0; ch < 36; ch++) | |||
| for(ch = 0; ch < font->size; ch++) | |||
| { | |||
| int diff = 0; | |||
| for(y = 0; y < 7; y++) | |||
| @@ -66,8 +60,7 @@ char *decode_authimage(struct image *img) | |||
| newx = 35.0 + (x + 6 * i) * 218.0 / 34.0 + y * 5.0 / 6.0 + 0.5; | |||
| newy = 33.0 - (x + 6 * i) * 18.0 / 34.0 + y * 42.0 / 6.0 + 0.5; | |||
| getpixel(tmp, newx, newy, &r, &g, &b); | |||
| getpixel(font, x + 6 * ch, y, &r2, &g, &b); | |||
| r = (r < 220) ? 0 : 255; | |||
| getpixel(font->img, x + 6 * ch, y, &r2, &g, &b); | |||
| diff += (r - r2) * (r - r2); | |||
| } | |||
| } | |||
| @@ -77,7 +70,7 @@ char *decode_authimage(struct image *img) | |||
| minch = ch; | |||
| } | |||
| } | |||
| result[i] = all[minch]; | |||
| result[i] = font->glyphs[minch].c; | |||
| } | |||
| image_free(tmp); | |||
| @@ -20,8 +20,6 @@ | |||
| static void find_glyphs(struct image *img); | |||
| /* Our macros */ | |||
| #define FONTNAME "font_clubic.png" | |||
| static struct image *font = NULL; | |||
| char *result; | |||
| /* Main function */ | |||
| @@ -29,18 +27,6 @@ char *decode_clubic(struct image *img) | |||
| { | |||
| struct image *tmp; | |||
| 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); | |||
| } | |||
| } | |||
| /* clubic captchas have 6 characters */ | |||
| result = malloc(7 * sizeof(char)); | |||
| strcpy(result, " "); | |||
| @@ -56,19 +42,20 @@ char *decode_clubic(struct image *img) | |||
| static void find_glyphs(struct image *img) | |||
| { | |||
| char all[] = "0123456789"; | |||
| struct | |||
| { | |||
| int xmin, xmax, ymin, ymax; | |||
| int count; | |||
| } | |||
| glyphs[10]; | |||
| static struct font *font = NULL; | |||
| struct image *tmp; | |||
| int x, y, i = 0; | |||
| int r, g, b; | |||
| int xmin, xmax, ymin, ymax, incell = 0, count = 0, startx = 0, cur = 0; | |||
| int xmin, xmax, ymin, ymax, startx = 0, cur = 0; | |||
| int distmin, distx, disty, distch; | |||
| if(!font) | |||
| { | |||
| font = font_load_variable("font_clubic.png", "0123456789"); | |||
| if(!font) | |||
| exit(1); | |||
| } | |||
| tmp = image_new(img->width, img->height); | |||
| for(y = 0; y < img->height; y++) | |||
| @@ -78,56 +65,17 @@ static void find_glyphs(struct image *img) | |||
| setpixel(tmp, x, y, 255, g, 255); | |||
| } | |||
| for(x = 0; x < font->width; x++) | |||
| { | |||
| int found = 0; | |||
| for(y = 0; y < font->height; y++) | |||
| { | |||
| getpixel(font, x, y, &r, &g, &b); | |||
| if(r < 128) | |||
| { | |||
| found = 1; | |||
| count += (255 - r); | |||
| } | |||
| } | |||
| if(found && !incell) | |||
| { | |||
| incell = 1; | |||
| xmin = x; | |||
| } | |||
| else if(!found && incell) | |||
| { | |||
| incell = 0; | |||
| xmax = x; | |||
| ymin = 0; | |||
| ymax = font->height; | |||
| glyphs[i].xmin = xmin; | |||
| glyphs[i].xmax = xmax; | |||
| glyphs[i].ymin = ymin; | |||
| glyphs[i].ymax = ymax; | |||
| glyphs[i].count = count; | |||
| count = 0; | |||
| i++; | |||
| } | |||
| } | |||
| if(i != 10) | |||
| { | |||
| printf("error: could not find 10 glyphs in font\n"); | |||
| exit(-1); | |||
| } | |||
| while(cur < 6) | |||
| { | |||
| /* Try to find 1st letter */ | |||
| distmin = INT_MAX; | |||
| for(i = 0; i < 10; i++) | |||
| for(i = 0; i < font->size; i++) | |||
| { | |||
| int localmin = INT_MAX, localx, localy; | |||
| xmin = glyphs[i].xmin; | |||
| ymin = glyphs[i].ymin; | |||
| xmax = glyphs[i].xmax; | |||
| ymax = glyphs[i].ymax; | |||
| xmin = font->glyphs[i].xmin; | |||
| ymin = font->glyphs[i].ymin; | |||
| xmax = font->glyphs[i].xmax; | |||
| ymax = font->glyphs[i].ymax; | |||
| for(y = -4; y < 4; y++) | |||
| for(x = startx; x < startx + 4; x++) | |||
| { | |||
| @@ -137,11 +85,11 @@ static void find_glyphs(struct image *img) | |||
| for(z = 0; z < xmax - xmin; z++) | |||
| { | |||
| int r2; | |||
| getgray(font, xmin + z, ymin + t, &r); | |||
| getgray(font->img, xmin + z, ymin + t, &r); | |||
| getgray(img, x + z, y + t, &r2); | |||
| dist += abs(r - r2); | |||
| } | |||
| dist = dist * 128 / glyphs[i].count; | |||
| dist = dist * 128 / font->glyphs[i].count; | |||
| if(dist < localmin) | |||
| { | |||
| localmin = dist; | |||
| @@ -159,20 +107,21 @@ static void find_glyphs(struct image *img) | |||
| } | |||
| /* Print min glyph */ | |||
| xmin = glyphs[distch].xmin; | |||
| ymin = glyphs[distch].ymin; | |||
| xmax = glyphs[distch].xmax; | |||
| ymax = glyphs[distch].ymax; | |||
| 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++) | |||
| { | |||
| getpixel(font, xmin + x, ymin + y, &r, &g, &b); | |||
| if(r > 128) continue; | |||
| getpixel(font->img, xmin + x, ymin + y, &r, &g, &b); | |||
| if(r > 128) | |||
| continue; | |||
| setpixel(tmp, distx + x, disty + y, r, g, b); | |||
| } | |||
| startx = distx + xmax - xmin; | |||
| result[cur++] = all[distch]; | |||
| result[cur++] = font->glyphs[distch].c; | |||
| } | |||
| image_free(tmp); | |||
| @@ -25,7 +25,9 @@ struct font | |||
| { | |||
| int xmin, xmax, ymin, ymax; | |||
| int count; /* Black pixel count */ | |||
| char c; | |||
| } *glyphs; | |||
| int size; | |||
| }; | |||
| /* global variables */ | |||
| @@ -57,6 +59,11 @@ int getgray(struct image *img, int x, int y, int *g); | |||
| int getpixel(struct image *img, int x, int y, int *r, int *g, int *b); | |||
| int setpixel(struct image *img, int x, int y, int r, int g, int b); | |||
| /* font operations */ | |||
| struct font *font_load_fixed(char *file, char *chars); | |||
| struct font *font_load_variable(char *file, char *chars); | |||
| void font_free(struct font *font); | |||
| /* image filters */ | |||
| void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b); | |||
| void filter_fill_holes(struct image *img); | |||
| @@ -0,0 +1,150 @@ | |||
| /* | |||
| * font.c: font handling | |||
| * $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 "config.h" | |||
| #include "common.h" | |||
| struct font *font_load_fixed(char *file, char *chars) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| struct font *font; | |||
| struct image *img; | |||
| int i; | |||
| sprintf(fontname, "%s/%s", share, file); | |||
| img = image_load(fontname); | |||
| if(!img) | |||
| { | |||
| fprintf(stderr, "%s: cannot load font %s\n", argv0, fontname); | |||
| return NULL; | |||
| } | |||
| font = malloc(sizeof(struct font)); | |||
| font->img = img; | |||
| font->size = strlen(chars); | |||
| font->glyphs = malloc(font->size * sizeof(struct glyph)); | |||
| for(i = 0; i < font->size; i++) | |||
| { | |||
| font->glyphs[i].xmin = i * font->img->width / font->size; | |||
| font->glyphs[i].xmax = (i + 1) * font->img->width / font->size; | |||
| font->glyphs[i].ymin = 0; | |||
| font->glyphs[i].ymax = font->img->height; | |||
| font->glyphs[i].count = 0; /* They all have the same width anyway */ | |||
| font->glyphs[i].c = chars[i]; | |||
| } | |||
| return font; | |||
| } | |||
| struct font *font_load_variable(char *file, char *chars) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| struct font *font; | |||
| struct image *img; | |||
| int count = 0, incell = 0, xmin, xmax, ymin, ymax; | |||
| int x, y, i; | |||
| int r, g, b; | |||
| sprintf(fontname, "%s/%s", share, file); | |||
| img = image_load(fontname); | |||
| if(!img) | |||
| { | |||
| fprintf(stderr, "%s: cannot load font %s\n", argv0, fontname); | |||
| return NULL; | |||
| } | |||
| font = malloc(sizeof(struct font)); | |||
| font->img = img; | |||
| font->size = strlen(chars); | |||
| font->glyphs = malloc(font->size * sizeof(struct glyph)); | |||
| for(x = 0, i = 0, xmin = 0; x < font->img->width && i < font->size; x++) | |||
| { | |||
| int found = 0; | |||
| for(y = 0; y < font->img->height; y++) | |||
| { | |||
| getpixel(font->img, x, y, &r, &g, &b); | |||
| if(r < 128) | |||
| { | |||
| found = 1; | |||
| count += (255 - r); | |||
| } | |||
| } | |||
| if(found && !incell) | |||
| { | |||
| incell = 1; | |||
| xmin = x; | |||
| } | |||
| else if(!found && incell) | |||
| { | |||
| incell = 0; | |||
| xmax = x; | |||
| #if 0 | |||
| ymin = font->img->height; | |||
| ymax = 0; | |||
| for(y = 0; y < font->img->height; y++) | |||
| { | |||
| int newx; | |||
| int gotit = 0; | |||
| for(newx = xmin; newx < xmax; newx++) | |||
| { | |||
| getpixel(font->img, newx, y, &r, &g, &b); | |||
| if(r < 128) | |||
| { | |||
| gotit = 1; | |||
| break; | |||
| } | |||
| } | |||
| if(gotit) | |||
| { | |||
| if(ymin > y) ymin = y; | |||
| if(ymax <= y) ymax = y + 1; | |||
| } | |||
| } | |||
| #else | |||
| ymin = 0; | |||
| ymax = font->img->height; | |||
| #endif | |||
| font->glyphs[i].xmin = xmin; | |||
| font->glyphs[i].xmax = xmax; | |||
| font->glyphs[i].ymin = ymin; | |||
| font->glyphs[i].ymax = ymax; | |||
| font->glyphs[i].count = count; | |||
| font->glyphs[i].c = chars[i]; | |||
| count = 0; | |||
| i++; | |||
| } | |||
| } | |||
| if(i != font->size) | |||
| { | |||
| printf("%s: could not find %i glyphs in font\n", argv0, font->size); | |||
| image_free(font->img); | |||
| free(font->glyphs); | |||
| free(font); | |||
| return NULL; | |||
| } | |||
| return font; | |||
| } | |||
| void font_free(struct font *font) | |||
| { | |||
| image_free(font->img); | |||
| free(font->glyphs); | |||
| free(font); | |||
| } | |||
| @@ -17,36 +17,31 @@ | |||
| #include "config.h" | |||
| #include "common.h" | |||
| #define FONTNAME "font_linuxfr.png" | |||
| static struct image *font = NULL; | |||
| /* Main function */ | |||
| char *decode_linuxfr(struct image *img) | |||
| { | |||
| char all[] = "abcdefghijklmnopqrstuvwxyz" | |||
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |||
| "0123456789"; | |||
| static struct font *font = NULL; | |||
| char *result; | |||
| struct image *tmp; | |||
| int x, y, r, g, b, i, j, c; | |||
| int *stats = malloc(img->height * sizeof(int)); | |||
| int *stats; | |||
| if(!font) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| sprintf(fontname, "%s/%s", share, FONTNAME); | |||
| font = image_load(fontname); | |||
| font = font_load_fixed("font_linuxfr.png", | |||
| "abcdefghijklmnopqrstuvwxyz" | |||
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |||
| "0123456789"); | |||
| if(!font) | |||
| { | |||
| fprintf(stderr, "cannot load font %s\n", fontname); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* linuxfr captchas have 7 characters */ | |||
| result = malloc(8 * sizeof(char)); | |||
| memset(result, '\0', 8); | |||
| stats = malloc(img->height * sizeof(int)); | |||
| tmp = image_dup(img); | |||
| filter_equalize(tmp, 150); | |||
| @@ -114,14 +109,14 @@ char *decode_linuxfr(struct image *img) | |||
| { | |||
| int r2, g2, b2, ch; | |||
| int minerror = INT_MAX; | |||
| for(ch = 0; ch < 62; ch++) | |||
| for(ch = 0; ch < font->size; ch++) | |||
| { | |||
| int error = 0, goodch = 1; | |||
| for(j = 0; j < 12 && goodch; j++) | |||
| for(i = 0; i < 8; i++) | |||
| { | |||
| getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b); | |||
| getpixel(font, ch * 9 + i, j, &r2, &g2, &b2); | |||
| getpixel(font->img, ch * 9 + i, j, &r2, &g2, &b2); | |||
| /* Only die if font is black and image is white */ | |||
| if(r > r2) | |||
| { | |||
| @@ -134,7 +129,7 @@ char *decode_linuxfr(struct image *img) | |||
| if(goodch && error < minerror) | |||
| { | |||
| minerror = error; | |||
| result[c] = all[ch]; | |||
| result[c] = font->glyphs[ch].c; | |||
| result[c+1] = '\0'; | |||
| } | |||
| } | |||
| @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) | |||
| switch(c) | |||
| { | |||
| case 'h': /* --help */ | |||
| printf("Usage: %s [OPTION]... FILE...\n", argv[0]); | |||
| printf("Usage: %s [OPTION]... IMAGE...\n", argv[0]); | |||
| #ifdef HAVE_GETOPT_LONG | |||
| printf(" -m, --mode <mode> force operating mode\n"); | |||
| printf(" -s, --share <dir> specify shared dir\n"); | |||
| @@ -17,14 +17,10 @@ | |||
| #include "config.h" | |||
| #include "common.h" | |||
| /* Our macros */ | |||
| #define FONTNAME "font_phpbb.png" | |||
| static struct image *font = NULL; | |||
| /* Main function */ | |||
| char *decode_phpbb(struct image *img) | |||
| { | |||
| char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; | |||
| static struct font *font = NULL; | |||
| char *result; | |||
| struct image *tmp1, *tmp2; | |||
| int x, y, i = 0; | |||
| @@ -34,14 +30,10 @@ char *decode_phpbb(struct image *img) | |||
| if(!font) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| sprintf(fontname, "%s/%s", share, FONTNAME); | |||
| font = image_load(fontname); | |||
| font = font_load_fixed("font_phpbb.png", | |||
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"); | |||
| if(!font) | |||
| { | |||
| fprintf(stderr, "cannot load font %s\n", fontname); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* phpBB captchas have 6 characters */ | |||
| @@ -68,14 +60,14 @@ char *decode_phpbb(struct image *img) | |||
| { | |||
| /* Try to find 1st letter */ | |||
| distmin = INT_MAX; | |||
| for(i = 0; i < 35; i++) | |||
| for(i = 0; i < font->size; i++) | |||
| { | |||
| int localmin = INT_MAX, localx, localy; | |||
| xmin = i * 40; | |||
| ymin = 0; | |||
| xmax = i * 40 + 40; | |||
| ymax = 40; | |||
| for(y = 0; y < img->height - 40; y++) | |||
| 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) | |||
| @@ -90,7 +82,7 @@ char *decode_phpbb(struct image *img) | |||
| for(z = 0; z < xmax - xmin; z++) | |||
| { | |||
| int r2; | |||
| getgray(font, xmin + z, ymin + t, &r); | |||
| getgray(font->img, xmin + z, ymin + t, &r); | |||
| getgray(tmp1, x + z, y + t, &r2); | |||
| if(r > r2) | |||
| dist += r - r2; | |||
| @@ -115,22 +107,23 @@ char *decode_phpbb(struct image *img) | |||
| } | |||
| /* Print min glyph (debug) */ | |||
| xmin = distch * 40; | |||
| ymin = 0; | |||
| xmax = distch * 40 + 40; | |||
| ymax = 40; | |||
| 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, xmin + x, ymin + y, &r2, &g, &b); | |||
| if(r2 > 128) continue; | |||
| 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] = all[distch]; | |||
| result[cur] = font->glyphs[distch].c; | |||
| } | |||
| image_free(tmp1); | |||
| @@ -20,15 +20,8 @@ | |||
| static void count_objects(struct image *img); | |||
| static void rotate(struct image *img); | |||
| static void cut_cells(struct image *img); | |||
| static void find_glyphs(struct image *img); | |||
| /* Our macros */ | |||
| #define FONTNAME "font_slashdot.png" | |||
| struct font font; | |||
| struct glyph glyphs[22]; | |||
| /* Global stuff */ | |||
| struct { int xmin, ymin, xmax, ymax; } objlist[100]; | |||
| int objects, first, last; | |||
| @@ -136,16 +129,6 @@ static void count_objects(struct image *img) | |||
| } | |||
| } | |||
| #if 0 | |||
| { CvPoint A, B; | |||
| A.x = (objlist[first].xmin + objlist[first].xmax) / 2; | |||
| A.y = (objlist[first].ymin + objlist[first].ymax) / 2; | |||
| B.x = (objlist[last].xmin + objlist[last].xmax) / 2; | |||
| B.y = (objlist[last].ymin + objlist[last].ymax) / 2; | |||
| cvLine(tmp, A, B, 0, 2.0, 0); | |||
| } | |||
| #endif | |||
| image_swap(img, tmp); | |||
| image_free(tmp); | |||
| } | |||
| @@ -195,58 +178,20 @@ static void rotate(struct image *img) | |||
| image_free(tmp); | |||
| } | |||
| static void cut_cells(struct image *img) | |||
| { | |||
| struct image *tmp; | |||
| int x, y; | |||
| int r, g, b; | |||
| 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, r, g, b); | |||
| } | |||
| for(x = 0; x < img->width; x++) | |||
| { | |||
| setpixel(tmp, x, 0, 255, 255, 255); | |||
| setpixel(tmp, x, img->height - 1, 255, 255, 255); | |||
| } | |||
| for(y = 0; y < img->height; y++) | |||
| for(x = 0; x < 7; x++) | |||
| { | |||
| setpixel(tmp, x * img->width / 7, y, 255, 255, 255); | |||
| setpixel(tmp, (x + 1) * img->width / 7 - 1, y, 255, 255, 255); | |||
| } | |||
| image_swap(img, tmp); | |||
| image_free(tmp); | |||
| } | |||
| static void find_glyphs(struct image *img) | |||
| { | |||
| char all[] = "abcdefgijkmnpqrstvwxyz"; | |||
| static struct font *font = NULL; | |||
| struct image *tmp; | |||
| int x, y, i = 0; | |||
| int r, g, b; | |||
| int xmin, xmax, ymin, ymax, incell = 0, count = 0, startx = 0, cur = 0; | |||
| int xmin, xmax, ymin, ymax, startx = 0, cur = 0; | |||
| int distmin, distx, disty, distch; | |||
| if(!font.img) | |||
| if(!font) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| sprintf(fontname, "%s/%s", share, FONTNAME); | |||
| font.img = image_load(fontname); | |||
| if(!font.img) | |||
| { | |||
| fprintf(stderr, "cannot load font %s\n", fontname); | |||
| exit(-1); | |||
| } | |||
| font.glyphs = glyphs; | |||
| font = font_load_variable("font_slashdot.png", "abcdefgijkmnpqrstvwxyz"); | |||
| if(!font) | |||
| exit(1); | |||
| } | |||
| tmp = image_new(img->width, img->height); | |||
| @@ -258,82 +203,17 @@ static void find_glyphs(struct image *img) | |||
| setpixel(tmp, x, y, 255, g, 255); | |||
| } | |||
| for(x = 0; x < font.img->width; x++) | |||
| { | |||
| int found = 0; | |||
| for(y = 0; y < font.img->height; y++) | |||
| { | |||
| getpixel(font.img, x, y, &r, &g, &b); | |||
| if(r < 128) | |||
| { | |||
| found = 1; | |||
| count += (255 - r); | |||
| } | |||
| } | |||
| if(found && !incell) | |||
| { | |||
| incell = 1; | |||
| xmin = x; | |||
| } | |||
| else if(!found && incell) | |||
| { | |||
| incell = 0; | |||
| xmax = x; | |||
| #if 0 | |||
| ymin = font.img->height; | |||
| ymax = 0; | |||
| for(y = 0; y < font.img->height; y++) | |||
| { | |||
| int newx; | |||
| int gotit = 0; | |||
| for(newx = xmin; newx < xmax; newx++) | |||
| { | |||
| getpixel(font.img, newx, y, &r, &g, &b); | |||
| if(r < 128) | |||
| { | |||
| gotit = 1; | |||
| break; | |||
| } | |||
| } | |||
| if(gotit) | |||
| { | |||
| if(ymin > y) ymin = y; | |||
| if(ymax <= y) ymax = y + 1; | |||
| } | |||
| } | |||
| #else | |||
| ymin = 0; | |||
| ymax = font.img->height; | |||
| #endif | |||
| font.glyphs[i].xmin = xmin; | |||
| font.glyphs[i].xmax = xmax; | |||
| font.glyphs[i].ymin = ymin; | |||
| font.glyphs[i].ymax = ymax; | |||
| font.glyphs[i].count = count; | |||
| count = 0; | |||
| i++; | |||
| } | |||
| } | |||
| if(i != 22) | |||
| { | |||
| printf("error: could not find 22 glyphs in font\n"); | |||
| exit(-1); | |||
| } | |||
| while(cur < 7) | |||
| { | |||
| /* Try to find 1st letter */ | |||
| distmin = INT_MAX; | |||
| for(i = 0; i < 22; i++) | |||
| for(i = 0; i < font->size; i++) | |||
| { | |||
| int localmin = INT_MAX, localx, localy; | |||
| //if(all[i] == 'i') continue; | |||
| xmin = font.glyphs[i].xmin; | |||
| ymin = font.glyphs[i].ymin; | |||
| xmax = font.glyphs[i].xmax; | |||
| ymax = font.glyphs[i].ymax; | |||
| //printf("trying to find %c (%i×%i) - ", all[i], xmax - xmin, ymax - ymin); | |||
| xmin = font->glyphs[i].xmin; | |||
| ymin = font->glyphs[i].ymin; | |||
| xmax = font->glyphs[i].xmax; | |||
| ymax = font->glyphs[i].ymax; | |||
| for(y = -5; y < 5; y++) | |||
| for(x = startx - 5; x < startx + 5; x++) | |||
| { | |||
| @@ -343,13 +223,13 @@ static void find_glyphs(struct image *img) | |||
| for(z = 0; z < xmax - xmin; z++) | |||
| { | |||
| int r2; | |||
| getgray(font.img, xmin + z, ymin + t, &r); | |||
| getgray(font->img, xmin + z, ymin + t, &r); | |||
| getgray(img, x + z, y + t, &r2); | |||
| dist += abs(r - r2); | |||
| } | |||
| // printf("%i %i -> %i\n", x, y, dist); | |||
| //dist /= sqrt(xmax - xmin); | |||
| dist = dist * 128 / font.glyphs[i].count; | |||
| dist = dist * 128 / font->glyphs[i].count; | |||
| if(dist < localmin) | |||
| { | |||
| localmin = dist; | |||
| @@ -367,24 +247,21 @@ static void find_glyphs(struct image *img) | |||
| } | |||
| } | |||
| //fprintf(stderr, "%i (%i,%i)\n", distmin, distx - startx, disty); | |||
| //printf("min diff: %c - %i (%i, %i)\n", all[distch], distmin, distx, disty); | |||
| /* Print min glyph */ | |||
| xmin = font.glyphs[distch].xmin; | |||
| ymin = font.glyphs[distch].ymin; | |||
| xmax = font.glyphs[distch].xmax; | |||
| ymax = font.glyphs[distch].ymax; | |||
| /* Draw best glyph in picture (debugging purposes) */ | |||
| 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++) | |||
| { | |||
| getpixel(font.img, xmin + x, ymin + y, &r, &g, &b); | |||
| getpixel(font->img, xmin + x, ymin + y, &r, &g, &b); | |||
| if(r > 128) continue; | |||
| setpixel(tmp, distx + x, disty + y, r, g, b); | |||
| } | |||
| startx = distx + xmax - xmin; | |||
| result[cur++] = all[distch]; | |||
| result[cur++] = font->glyphs[distch].c; | |||
| } | |||
| image_swap(img, tmp); | |||
| @@ -18,35 +18,21 @@ | |||
| #include "config.h" | |||
| #include "common.h" | |||
| /* Our macros */ | |||
| #define FONTNAME "font_phpbb.png" | |||
| static void find_glyphs(struct image *img); | |||
| /* Global stuff */ | |||
| struct { int xmin, ymin, xmax, ymax; } objlist[100]; | |||
| int objects, first, last; | |||
| char *result; | |||
| /* Main function */ | |||
| char *decode_test(struct image *img) | |||
| { | |||
| char *result; | |||
| struct image *tmp; | |||
| /* Initialise local data */ | |||
| objects = 0; | |||
| first = -1; | |||
| last = -1; | |||
| /* phpBB captchas have 6 characters */ | |||
| result = malloc(7 * sizeof(char)); | |||
| result[0] = 0; | |||
| tmp = image_dup(img); | |||
| filter_smooth(tmp); | |||
| filter_median(tmp); | |||
| filter_equalize(tmp, 130); | |||
| filter_median(tmp); | |||
| find_glyphs(tmp); | |||
| image_free(tmp); | |||
| @@ -55,105 +41,3 @@ char *decode_test(struct image *img) | |||
| /* The following functions are local */ | |||
| static void find_glyphs(struct image *img) | |||
| { | |||
| char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; | |||
| struct image *tmp, *font; | |||
| int x, y, i = 0; | |||
| int r, g, b; | |||
| int xmin, xmax, ymin, ymax, cur = 0, offset = -1; | |||
| int distmin, distx, disty, distch; | |||
| 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); | |||
| } | |||
| } | |||
| tmp = image_new(img->width, img->height); | |||
| for(x = 0; x < img->width; x++) | |||
| for(y = 0; y < img->height; y++) | |||
| { | |||
| getpixel(img, x, y, &r, &g, &b); | |||
| setpixel(tmp, x, y, 255, g, 255); | |||
| if(r == 0 && offset == -1) | |||
| offset = x; | |||
| } | |||
| strcpy(result, " "); | |||
| while(cur < 6) | |||
| { | |||
| /* Try to find 1st letter */ | |||
| distmin = INT_MAX; | |||
| for(i = 0; i < 35; i++) | |||
| { | |||
| int localmin = INT_MAX, localx, localy; | |||
| xmin = i * 40; | |||
| ymin = 0; | |||
| xmax = i * 40 + 40; | |||
| ymax = 40; | |||
| for(y = 0; y < img->height - 40; y++) | |||
| { | |||
| x = offset - 5; | |||
| if(cur == 0) | |||
| x -= 15; | |||
| if(x < 0) | |||
| x = 0; | |||
| for(; x < offset + 10; 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, xmin + z, ymin + t, &r); | |||
| getgray(img, x + z, y + t, &r2); | |||
| dist += abs(r - r2); | |||
| } | |||
| 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 = distch * 40; | |||
| ymin = 0; | |||
| xmax = distch * 40 + 40; | |||
| ymax = 40; | |||
| for(y = 0; y < ymax - ymin; y++) | |||
| for(x = 0; x < xmax - xmin; x++) | |||
| { | |||
| getpixel(font, xmin + x, ymin + y, &r, &g, &b); | |||
| if(r > 128) continue; | |||
| setpixel(tmp, distx + x, disty + y, r, g, b); | |||
| } | |||
| offset = distx + xmax - xmin; | |||
| result[cur++] = all[distch]; | |||
| } | |||
| image_swap(img, tmp); | |||
| image_free(tmp); | |||
| } | |||
| @@ -17,13 +17,10 @@ | |||
| #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"; | |||
| static struct font *font = NULL; | |||
| char *result; | |||
| struct image *tmp; | |||
| int limits[6] = { 26, 53, 80, 107, 134, 160 }; | |||
| @@ -31,14 +28,10 @@ char *decode_vbulletin(struct image *img) | |||
| if(!font) | |||
| { | |||
| char fontname[BUFSIZ]; | |||
| sprintf(fontname, "%s/%s", share, FONTNAME); | |||
| font = image_load(fontname); | |||
| font = font_load_fixed("font_vbulletin.png", | |||
| "2346789ABCDEFGHJKLMNPRTWXYZ"); | |||
| if(!font) | |||
| { | |||
| fprintf(stderr, "cannot load font %s\n", fontname); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* vBulletin captchas have 6 characters */ | |||
| @@ -114,18 +107,16 @@ char *decode_vbulletin(struct image *img) | |||
| /* Guess all glyphs */ | |||
| for(i = 0; i < 6; i++) | |||
| { | |||
| struct image *new = image_dup(tmp); | |||
| int mindist = INT_MAX, min = -1; | |||
| filter_crop(new, limits[i], 15, limits[i] + 11, 45); | |||
| for(j = 0; j < 27; j++) | |||
| for(j = 0; j < font->size; j++) | |||
| { | |||
| int dist = 0; | |||
| for(y = 0; y < new->height; y++) | |||
| for(x = 0; x < new->width; x++) | |||
| for(y = 0; y < 11; y++) | |||
| for(x = 0; x < 30; x++) | |||
| { | |||
| int r2, g2, b2; | |||
| getpixel(font, 12 * j + x, y, &r, &g, &b); | |||
| getpixel(new, x, y, &r2, &g2, &b2); | |||
| getpixel(font->img, 12 * j + x, y, &r, &g, &b); | |||
| getpixel(tmp, limits[i] + x, 15 + y, &r2, &g2, &b2); | |||
| dist += (r - r2) * (r - r2); | |||
| } | |||
| if(dist < mindist) | |||
| @@ -134,8 +125,7 @@ char *decode_vbulletin(struct image *img) | |||
| min = j; | |||
| } | |||
| } | |||
| image_free(new); | |||
| result[i] = all[min]; | |||
| result[i] = font->glyphs[min].c; | |||
| } | |||
| image_free(tmp); | |||
| @@ -20,27 +20,36 @@ | |||
| static void fill_white_holes(struct image *img); | |||
| /* Our macros */ | |||
| #define FACTOR 1 | |||
| #define FONTNAME "font_xanga.png" // use with FACTOR = 1 | |||
| //#define FONTNAME "font.png" // use with FACTOR = 2 | |||
| //#define FONTNAME "font_dilated.png" // use with FACTOR = 2 | |||
| static struct image *font = NULL; | |||
| /* Global stuff */ | |||
| struct { int xmin, ymin, xmax, ymax; } objlist[100]; | |||
| int objects, first, last; | |||
| char *result; | |||
| /* Main function */ | |||
| char *decode_xanga(struct image *img) | |||
| { | |||
| static struct font *font1 = NULL, *font2 = NULL, *font3 = NULL; | |||
| struct image *tmp; | |||
| /* Initialise local data */ | |||
| objects = 0; | |||
| first = -1; | |||
| last = -1; | |||
| 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)); | |||
| @@ -68,7 +77,6 @@ return NULL; | |||
| filter_equalize(tmp, 200); | |||
| /* Invert rotation and find glyphs */ | |||
| rotate(tmp); | |||
| filter_median(tmp); | |||
| /* Clean up our mess */ | |||
| @@ -86,7 +94,7 @@ return NULL; | |||
| static void fill_white_holes(struct image *img) | |||
| { | |||
| struct image *tmp; | |||
| int x, y, i; | |||
| int x, y; | |||
| int r, g, b; | |||
| tmp = image_new(img->width, img->height); | |||