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 | bin_PROGRAMS = pwntcha | ||||
pwntcha_SOURCES = \ | pwntcha_SOURCES = \ | ||||
main.c \ | main.c \ | ||||
filter.c \ | |||||
font.c \ | |||||
image.c \ | image.c \ | ||||
filters.c \ | |||||
common.h \ | common.h \ | ||||
authimage.c \ | authimage.c \ | ||||
clubic.c \ | clubic.c \ | ||||
@@ -18,44 +18,38 @@ | |||||
#include "config.h" | #include "config.h" | ||||
#include "common.h" | #include "common.h" | ||||
#define FONTNAME "font_authimage.png" | |||||
static struct image *font = NULL; | |||||
/* Main function */ | /* Main function */ | ||||
char *decode_authimage(struct image *img) | char *decode_authimage(struct image *img) | ||||
{ | { | ||||
char *all = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |||||
static struct font *font = NULL; | |||||
char *result; | char *result; | ||||
struct image *tmp; | struct image *tmp; | ||||
int x, y, r, g, b, i; | int x, y, r, g, b, i; | ||||
if(!font) | 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) | if(!font) | ||||
{ | |||||
fprintf(stderr, "cannot load font %s\n", fontname); | |||||
exit(-1); | exit(-1); | ||||
} | |||||
} | } | ||||
/* authimage captchas have 6 characters */ | /* authimage captchas have 6 characters */ | ||||
result = malloc(7 * sizeof(char)); | result = malloc(7 * sizeof(char)); | ||||
memset(result, '\0', 7); | 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); | tmp = image_dup(img); | ||||
filter_scale(tmp, 2.0); | filter_scale(tmp, 2.0); | ||||
getpixel(tmp, 0, 0, &r, &g, &b); | getpixel(tmp, 0, 0, &r, &g, &b); | ||||
filter_equalize(tmp, r * 3 / 4); | filter_equalize(tmp, r * 3 / 4); | ||||
filter_smooth(tmp); | filter_smooth(tmp); | ||||
filter_equalize(tmp, 220); | |||||
for(i = 0; i < 6; i++) | for(i = 0; i < 6; i++) | ||||
{ | { | ||||
int mindiff = INT_MAX, minch = -1, ch; | int mindiff = INT_MAX, minch = -1, ch; | ||||
for(ch = 0; ch < 36; ch++) | |||||
for(ch = 0; ch < font->size; ch++) | |||||
{ | { | ||||
int diff = 0; | int diff = 0; | ||||
for(y = 0; y < 7; y++) | 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; | 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; | 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(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); | diff += (r - r2) * (r - r2); | ||||
} | } | ||||
} | } | ||||
@@ -77,7 +70,7 @@ char *decode_authimage(struct image *img) | |||||
minch = ch; | minch = ch; | ||||
} | } | ||||
} | } | ||||
result[i] = all[minch]; | |||||
result[i] = font->glyphs[minch].c; | |||||
} | } | ||||
image_free(tmp); | image_free(tmp); | ||||
@@ -20,8 +20,6 @@ | |||||
static void find_glyphs(struct image *img); | static void find_glyphs(struct image *img); | ||||
/* Our macros */ | /* Our macros */ | ||||
#define FONTNAME "font_clubic.png" | |||||
static struct image *font = NULL; | |||||
char *result; | char *result; | ||||
/* Main function */ | /* Main function */ | ||||
@@ -29,18 +27,6 @@ char *decode_clubic(struct image *img) | |||||
{ | { | ||||
struct image *tmp; | 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 */ | /* clubic captchas have 6 characters */ | ||||
result = malloc(7 * sizeof(char)); | result = malloc(7 * sizeof(char)); | ||||
strcpy(result, " "); | strcpy(result, " "); | ||||
@@ -56,19 +42,20 @@ char *decode_clubic(struct image *img) | |||||
static void find_glyphs(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; | struct image *tmp; | ||||
int x, y, i = 0; | int x, y, i = 0; | ||||
int r, g, b; | 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; | 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); | tmp = image_new(img->width, img->height); | ||||
for(y = 0; y < img->height; y++) | 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); | 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) | while(cur < 6) | ||||
{ | { | ||||
/* Try to find 1st letter */ | /* Try to find 1st letter */ | ||||
distmin = INT_MAX; | distmin = INT_MAX; | ||||
for(i = 0; i < 10; i++) | |||||
for(i = 0; i < font->size; i++) | |||||
{ | { | ||||
int localmin = INT_MAX, localx, localy; | 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(y = -4; y < 4; y++) | ||||
for(x = startx; x < startx + 4; x++) | 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++) | for(z = 0; z < xmax - xmin; z++) | ||||
{ | { | ||||
int r2; | int r2; | ||||
getgray(font, xmin + z, ymin + t, &r); | |||||
getgray(font->img, xmin + z, ymin + t, &r); | |||||
getgray(img, x + z, y + t, &r2); | getgray(img, x + z, y + t, &r2); | ||||
dist += abs(r - r2); | dist += abs(r - r2); | ||||
} | } | ||||
dist = dist * 128 / glyphs[i].count; | |||||
dist = dist * 128 / font->glyphs[i].count; | |||||
if(dist < localmin) | if(dist < localmin) | ||||
{ | { | ||||
localmin = dist; | localmin = dist; | ||||
@@ -159,20 +107,21 @@ static void find_glyphs(struct image *img) | |||||
} | } | ||||
/* Print min glyph */ | /* 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(y = 0; y < ymax - ymin; y++) | ||||
for(x = 0; x < xmax - xmin; x++) | 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); | setpixel(tmp, distx + x, disty + y, r, g, b); | ||||
} | } | ||||
startx = distx + xmax - xmin; | startx = distx + xmax - xmin; | ||||
result[cur++] = all[distch]; | |||||
result[cur++] = font->glyphs[distch].c; | |||||
} | } | ||||
image_free(tmp); | image_free(tmp); | ||||
@@ -25,7 +25,9 @@ struct font | |||||
{ | { | ||||
int xmin, xmax, ymin, ymax; | int xmin, xmax, ymin, ymax; | ||||
int count; /* Black pixel count */ | int count; /* Black pixel count */ | ||||
char c; | |||||
} *glyphs; | } *glyphs; | ||||
int size; | |||||
}; | }; | ||||
/* global variables */ | /* 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 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); | 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 */ | /* image filters */ | ||||
void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b); | void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b); | ||||
void filter_fill_holes(struct image *img); | 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 "config.h" | ||||
#include "common.h" | #include "common.h" | ||||
#define FONTNAME "font_linuxfr.png" | |||||
static struct image *font = NULL; | |||||
/* Main function */ | /* Main function */ | ||||
char *decode_linuxfr(struct image *img) | char *decode_linuxfr(struct image *img) | ||||
{ | { | ||||
char all[] = "abcdefghijklmnopqrstuvwxyz" | |||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |||||
"0123456789"; | |||||
static struct font *font = NULL; | |||||
char *result; | char *result; | ||||
struct image *tmp; | struct image *tmp; | ||||
int x, y, r, g, b, i, j, c; | int x, y, r, g, b, i, j, c; | ||||
int *stats = malloc(img->height * sizeof(int)); | |||||
int *stats; | |||||
if(!font) | 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) | if(!font) | ||||
{ | |||||
fprintf(stderr, "cannot load font %s\n", fontname); | |||||
exit(-1); | exit(-1); | ||||
} | |||||
} | } | ||||
/* linuxfr captchas have 7 characters */ | /* linuxfr captchas have 7 characters */ | ||||
result = malloc(8 * sizeof(char)); | result = malloc(8 * sizeof(char)); | ||||
memset(result, '\0', 8); | memset(result, '\0', 8); | ||||
stats = malloc(img->height * sizeof(int)); | |||||
tmp = image_dup(img); | tmp = image_dup(img); | ||||
filter_equalize(tmp, 150); | filter_equalize(tmp, 150); | ||||
@@ -114,14 +109,14 @@ char *decode_linuxfr(struct image *img) | |||||
{ | { | ||||
int r2, g2, b2, ch; | int r2, g2, b2, ch; | ||||
int minerror = INT_MAX; | int minerror = INT_MAX; | ||||
for(ch = 0; ch < 62; ch++) | |||||
for(ch = 0; ch < font->size; ch++) | |||||
{ | { | ||||
int error = 0, goodch = 1; | int error = 0, goodch = 1; | ||||
for(j = 0; j < 12 && goodch; j++) | for(j = 0; j < 12 && goodch; j++) | ||||
for(i = 0; i < 8; i++) | for(i = 0; i < 8; i++) | ||||
{ | { | ||||
getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b); | 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 */ | /* Only die if font is black and image is white */ | ||||
if(r > r2) | if(r > r2) | ||||
{ | { | ||||
@@ -134,7 +129,7 @@ char *decode_linuxfr(struct image *img) | |||||
if(goodch && error < minerror) | if(goodch && error < minerror) | ||||
{ | { | ||||
minerror = error; | minerror = error; | ||||
result[c] = all[ch]; | |||||
result[c] = font->glyphs[ch].c; | |||||
result[c+1] = '\0'; | result[c+1] = '\0'; | ||||
} | } | ||||
} | } | ||||
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) | |||||
switch(c) | switch(c) | ||||
{ | { | ||||
case 'h': /* --help */ | case 'h': /* --help */ | ||||
printf("Usage: %s [OPTION]... FILE...\n", argv[0]); | |||||
printf("Usage: %s [OPTION]... IMAGE...\n", argv[0]); | |||||
#ifdef HAVE_GETOPT_LONG | #ifdef HAVE_GETOPT_LONG | ||||
printf(" -m, --mode <mode> force operating mode\n"); | printf(" -m, --mode <mode> force operating mode\n"); | ||||
printf(" -s, --share <dir> specify shared dir\n"); | printf(" -s, --share <dir> specify shared dir\n"); | ||||
@@ -17,14 +17,10 @@ | |||||
#include "config.h" | #include "config.h" | ||||
#include "common.h" | #include "common.h" | ||||
/* Our macros */ | |||||
#define FONTNAME "font_phpbb.png" | |||||
static struct image *font = NULL; | |||||
/* Main function */ | /* Main function */ | ||||
char *decode_phpbb(struct image *img) | char *decode_phpbb(struct image *img) | ||||
{ | { | ||||
char all[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"; | |||||
static struct font *font = NULL; | |||||
char *result; | char *result; | ||||
struct image *tmp1, *tmp2; | struct image *tmp1, *tmp2; | ||||
int x, y, i = 0; | int x, y, i = 0; | ||||
@@ -34,14 +30,10 @@ char *decode_phpbb(struct image *img) | |||||
if(!font) | 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) | if(!font) | ||||
{ | |||||
fprintf(stderr, "cannot load font %s\n", fontname); | |||||
exit(-1); | exit(-1); | ||||
} | |||||
} | } | ||||
/* phpBB captchas have 6 characters */ | /* phpBB captchas have 6 characters */ | ||||
@@ -68,14 +60,14 @@ char *decode_phpbb(struct image *img) | |||||
{ | { | ||||
/* Try to find 1st letter */ | /* Try to find 1st letter */ | ||||
distmin = INT_MAX; | distmin = INT_MAX; | ||||
for(i = 0; i < 35; i++) | |||||
for(i = 0; i < font->size; i++) | |||||
{ | { | ||||
int localmin = INT_MAX, localx, localy; | 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; | x = offset - 3; | ||||
if(cur == 0) | if(cur == 0) | ||||
@@ -90,7 +82,7 @@ char *decode_phpbb(struct image *img) | |||||
for(z = 0; z < xmax - xmin; z++) | for(z = 0; z < xmax - xmin; z++) | ||||
{ | { | ||||
int r2; | int r2; | ||||
getgray(font, xmin + z, ymin + t, &r); | |||||
getgray(font->img, xmin + z, ymin + t, &r); | |||||
getgray(tmp1, x + z, y + t, &r2); | getgray(tmp1, x + z, y + t, &r2); | ||||
if(r > r2) | if(r > r2) | ||||
dist += r - r2; | dist += r - r2; | ||||
@@ -115,22 +107,23 @@ char *decode_phpbb(struct image *img) | |||||
} | } | ||||
/* Print min glyph (debug) */ | /* 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(y = 0; y < ymax - ymin; y++) | ||||
for(x = 0; x < xmax - xmin; x++) | for(x = 0; x < xmax - xmin; x++) | ||||
{ | { | ||||
int r2; | 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); | getpixel(tmp2, distx + x, disty + y, &r, &g, &b); | ||||
setpixel(tmp2, distx + x, disty + y, r2, g, b); | setpixel(tmp2, distx + x, disty + y, r2, g, b); | ||||
} | } | ||||
offset = distx + xmax - xmin; | offset = distx + xmax - xmin; | ||||
result[cur] = all[distch]; | |||||
result[cur] = font->glyphs[distch].c; | |||||
} | } | ||||
image_free(tmp1); | image_free(tmp1); | ||||
@@ -20,15 +20,8 @@ | |||||
static void count_objects(struct image *img); | static void count_objects(struct image *img); | ||||
static void rotate(struct image *img); | static void rotate(struct image *img); | ||||
static void cut_cells(struct image *img); | |||||
static void find_glyphs(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 */ | /* Global stuff */ | ||||
struct { int xmin, ymin, xmax, ymax; } objlist[100]; | struct { int xmin, ymin, xmax, ymax; } objlist[100]; | ||||
int objects, first, last; | 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_swap(img, tmp); | ||||
image_free(tmp); | image_free(tmp); | ||||
} | } | ||||
@@ -195,58 +178,20 @@ static void rotate(struct image *img) | |||||
image_free(tmp); | 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) | static void find_glyphs(struct image *img) | ||||
{ | { | ||||
char all[] = "abcdefgijkmnpqrstvwxyz"; | |||||
static struct font *font = NULL; | |||||
struct image *tmp; | struct image *tmp; | ||||
int x, y, i = 0; | int x, y, i = 0; | ||||
int r, g, b; | 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; | 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); | 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); | 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) | while(cur < 7) | ||||
{ | { | ||||
/* Try to find 1st letter */ | /* Try to find 1st letter */ | ||||
distmin = INT_MAX; | distmin = INT_MAX; | ||||
for(i = 0; i < 22; i++) | |||||
for(i = 0; i < font->size; i++) | |||||
{ | { | ||||
int localmin = INT_MAX, localx, localy; | 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(y = -5; y < 5; y++) | ||||
for(x = startx - 5; x < startx + 5; x++) | 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++) | for(z = 0; z < xmax - xmin; z++) | ||||
{ | { | ||||
int r2; | 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); | getgray(img, x + z, y + t, &r2); | ||||
dist += abs(r - r2); | dist += abs(r - r2); | ||||
} | } | ||||
// printf("%i %i -> %i\n", x, y, dist); | // printf("%i %i -> %i\n", x, y, dist); | ||||
//dist /= sqrt(xmax - xmin); | //dist /= sqrt(xmax - xmin); | ||||
dist = dist * 128 / font.glyphs[i].count; | |||||
dist = dist * 128 / font->glyphs[i].count; | |||||
if(dist < localmin) | if(dist < localmin) | ||||
{ | { | ||||
localmin = dist; | 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(y = 0; y < ymax - ymin; y++) | ||||
for(x = 0; x < xmax - xmin; x++) | 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; | if(r > 128) continue; | ||||
setpixel(tmp, distx + x, disty + y, r, g, b); | setpixel(tmp, distx + x, disty + y, r, g, b); | ||||
} | } | ||||
startx = distx + xmax - xmin; | startx = distx + xmax - xmin; | ||||
result[cur++] = all[distch]; | |||||
result[cur++] = font->glyphs[distch].c; | |||||
} | } | ||||
image_swap(img, tmp); | image_swap(img, tmp); | ||||
@@ -18,35 +18,21 @@ | |||||
#include "config.h" | #include "config.h" | ||||
#include "common.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 */ | /* Main function */ | ||||
char *decode_test(struct image *img) | char *decode_test(struct image *img) | ||||
{ | { | ||||
char *result; | |||||
struct image *tmp; | struct image *tmp; | ||||
/* Initialise local data */ | |||||
objects = 0; | |||||
first = -1; | |||||
last = -1; | |||||
/* phpBB captchas have 6 characters */ | /* phpBB captchas have 6 characters */ | ||||
result = malloc(7 * sizeof(char)); | result = malloc(7 * sizeof(char)); | ||||
result[0] = 0; | |||||
tmp = image_dup(img); | tmp = image_dup(img); | ||||
filter_smooth(tmp); | filter_smooth(tmp); | ||||
filter_median(tmp); | filter_median(tmp); | ||||
filter_equalize(tmp, 130); | filter_equalize(tmp, 130); | ||||
filter_median(tmp); | filter_median(tmp); | ||||
find_glyphs(tmp); | |||||
image_free(tmp); | image_free(tmp); | ||||
@@ -55,105 +41,3 @@ char *decode_test(struct image *img) | |||||
/* The following functions are local */ | /* 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 "config.h" | ||||
#include "common.h" | #include "common.h" | ||||
#define FONTNAME "font_vbulletin.png" | |||||
static struct image *font = NULL; | |||||
/* Main function */ | /* Main function */ | ||||
char *decode_vbulletin(struct image *img) | char *decode_vbulletin(struct image *img) | ||||
{ | { | ||||
char all[] = "2346789ABCDEFGHJKLMNPRTWXYZ"; | |||||
static struct font *font = NULL; | |||||
char *result; | char *result; | ||||
struct image *tmp; | struct image *tmp; | ||||
int limits[6] = { 26, 53, 80, 107, 134, 160 }; | int limits[6] = { 26, 53, 80, 107, 134, 160 }; | ||||
@@ -31,14 +28,10 @@ char *decode_vbulletin(struct image *img) | |||||
if(!font) | 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) | if(!font) | ||||
{ | |||||
fprintf(stderr, "cannot load font %s\n", fontname); | |||||
exit(-1); | exit(-1); | ||||
} | |||||
} | } | ||||
/* vBulletin captchas have 6 characters */ | /* vBulletin captchas have 6 characters */ | ||||
@@ -114,18 +107,16 @@ char *decode_vbulletin(struct image *img) | |||||
/* Guess all glyphs */ | /* Guess all glyphs */ | ||||
for(i = 0; i < 6; i++) | for(i = 0; i < 6; i++) | ||||
{ | { | ||||
struct image *new = image_dup(tmp); | |||||
int mindist = INT_MAX, min = -1; | 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; | 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; | 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); | dist += (r - r2) * (r - r2); | ||||
} | } | ||||
if(dist < mindist) | if(dist < mindist) | ||||
@@ -134,8 +125,7 @@ char *decode_vbulletin(struct image *img) | |||||
min = j; | min = j; | ||||
} | } | ||||
} | } | ||||
image_free(new); | |||||
result[i] = all[min]; | |||||
result[i] = font->glyphs[min].c; | |||||
} | } | ||||
image_free(tmp); | image_free(tmp); | ||||
@@ -20,27 +20,36 @@ | |||||
static void fill_white_holes(struct image *img); | 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 */ | /* Main function */ | ||||
char *decode_xanga(struct image *img) | char *decode_xanga(struct image *img) | ||||
{ | { | ||||
static struct font *font1 = NULL, *font2 = NULL, *font3 = NULL; | |||||
struct image *tmp; | 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 */ | /* Xanga captchas have 7 characters */ | ||||
result = malloc(8 * sizeof(char)); | result = malloc(8 * sizeof(char)); | ||||
@@ -68,7 +77,6 @@ return NULL; | |||||
filter_equalize(tmp, 200); | filter_equalize(tmp, 200); | ||||
/* Invert rotation and find glyphs */ | /* Invert rotation and find glyphs */ | ||||
rotate(tmp); | |||||
filter_median(tmp); | filter_median(tmp); | ||||
/* Clean up our mess */ | /* Clean up our mess */ | ||||
@@ -86,7 +94,7 @@ return NULL; | |||||
static void fill_white_holes(struct image *img) | static void fill_white_holes(struct image *img) | ||||
{ | { | ||||
struct image *tmp; | struct image *tmp; | ||||
int x, y, i; | |||||
int x, y; | |||||
int r, g, b; | int r, g, b; | ||||
tmp = image_new(img->width, img->height); | tmp = image_new(img->width, img->height); | ||||