/* Main function */ char *decode_authimage(struct image *img) { static struct font *font = NULL; char *result; struct image *tmp; int x, y, r, g, b, i; if(!font) { font = font_load_fixed(DECODER, "font.png", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); if(!font) exit(-1); } /* authimage captchas have 6 characters */ result = malloc(7 * sizeof(char)); memset(result, '\0', 7); /* 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_threshold(tmp, r * 3 / 4); filter_smooth(tmp); filter_threshold(tmp, 220); for(i = 0; i < 6; i++) { int mindiff = INT_MAX, minch = -1, ch; for(ch = 0; ch < font->size; ch++) { int diff = 0; for(y = 0; y < 7; y++) { for(x = 0; x < 5; x++) { int newx, newy, r2; 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->img, x + 6 * ch, y, &r2, &g, &b); diff += (r - r2) * (r - r2); } } if(diff < mindiff) { mindiff = diff; minch = ch; } } result[i] = font->glyphs[minch].c; } image_free(tmp); return result; }
/* Main function */ char *decode_vbulletin(struct image *img) { static struct font *font = NULL; char *result; struct image *tmp; int limits[6] = { 26, 53, 80, 107, 134, 160 }; int x, y, r, g, b, i, j; if(!font) { font = font_load_fixed(DECODER, "font.png", "2346789ABCDEFGHJKLMNPRTWXYZ"); if(!font) 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 */ tmp = image_dup(img); getpixel(tmp, 0, 0, &r, &g, &b); if(r < 50) filter_threshold(tmp, 128); else filter_threshold(tmp, -128); /* Remove garbage around the cells */ for(x = 0; x < tmp->width; x++) { for(y = 0; y < 15; y++) setpixel(tmp, x, y, 255, 255, 255); for(y = 45; y < tmp->height; y++) setpixel(tmp, x, y, 255, 255, 255); } for(x = 0; x < tmp->width; x++) { for(i = 0; i < 6; i++) if(x == limits[i]) break; if(i == 6) for(y = 15; y < 45; y++) setpixel(tmp, x, y, 255, 255, 255); else x += 11; } filter_black_stuff(tmp); filter_black_stuff(tmp); /* Fill letters in gray */ for(x = 26; x < 172; x++) { getpixel(tmp, x, 15, &r, &g, &b); if(r == 0) filter_flood_fill(tmp, 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(tmp, x, y, &r, &g, &b); if(r == 0) filter_flood_fill(tmp, x, y, 255, 255, 255); } /* Fill letters in black */ for(x = 26; x < 172; x++) { getpixel(tmp, x, 44, &r, &g, &b); if(r == 127) filter_flood_fill(tmp, 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(tmp, x, y, &r, &g, &b); if(r == 127) filter_flood_fill(tmp, x, y, 255, 255, 255); } /* Guess all glyphs */ for(i = 0; i < 6; i++) { int mindist = INT_MAX, min = -1; for(j = 0; j < font->size; j++) { int dist = 0; for(y = 0; y < 30; y++) for(x = 0; x < 11; x++) { int 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) { mindist = dist; min = j; } } result[i] = font->glyphs[min].c; } image_free(tmp); return result; }
/* Main function */ char *decode_linuxfr(struct image *img) { static struct font *font = NULL; char *result; struct image *tmp; int x, y, r, g, b, i, j, c; int *stats; if(!font) { font = font_load_fixed(DECODER, "font.png", "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"); if(!font) 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_threshold(tmp, 150); for(y = 0; y < tmp->height; y++) { int count = 0; for(x = 0; x < tmp->width; x++) { getpixel(tmp, x, y, &r, &g, &b); if(r == 0) count++; } stats[y] = count; } /* Find 7 consecutive lines that have at least 14 pixels; they're * baseline candidates */ for(y = 0; y < tmp->height - 11; y++) { int ycan = 1; for(j = 3; j < 10; j++) { if(stats[y + j] < 14) { ycan = 0; y = y + j - 3; break; } } if(!ycan) continue; /* Find 7 consecutive cells that have at least 2 pixels on * each line; they're base column candidates */ for(x = 0; x < tmp->width - 9 * 7 + 1; x++) { int goodx = 1; for(c = 0; c < 7 && goodx; c++) { for(j = 3; j < 10; j++) { int count = 0; for(i = 0; i < 8; i++) { getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b); if(r == 0) { count++; if(count == 2) break; } } if(count < 2) { goodx = 0; break; } } } if(!goodx) continue; /* Now we have an (x,y) candidate - try to fit 7 characters */ for(c = 0; c < 7 && goodx; c++) { int r2, g2, b2, ch; int minerror = INT_MAX; 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->img, ch * 9 + i, j, &r2, &g2, &b2); /* Only die if font is black and image is white */ if(r > r2) { goodch = 0; break; } else if(r < r2) error++; } if(goodch && error < minerror) { minerror = error; result[c] = font->glyphs[ch].c; result[c+1] = '\0'; } } if(minerror == INT_MAX) goodx = 0; } /* Wow, that was a good guess! Exit this loop */ if(goodx) break; } } image_free(tmp); free(stats); if(strlen(result) != 7) { free(result); return NULL; } return result; }