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); | |||