source: pwntcha/trunk/src/xanga.c @ 482

Last change on this file since 482 was 482, checked in by Sam Hocevar, 15 years ago
  • filter_equalize -> filter_threshold
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 * xanga.c: decode Xanga captchas
3 * $Id: xanga.c 482 2005-05-30 15:22:02Z sam $
4 *
5 * Copyright: (c) 2005 Sam Hocevar <sam@zoy.org>
6 *   This program is free software; you can redistribute it and/or
7 *   modify it under the terms of the Do What The Fuck You Want To
8 *   Public License as published by Banlu Kemiyatorn. See
9 *   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <limits.h>
16#include <math.h>
17
18#include "config.h"
19#include "common.h"
20
21static void fill_white_holes(struct image *img);
22static void find_glyphs(struct image *img);
23
24static char *result;
25
26/* Main function */
27char *decode_xanga(struct image *img)
28{
29    struct image *tmp;
30
31    /* Xanga captchas have 6 characters */
32    result = malloc(7 * sizeof(char));
33    strcpy(result, "      ");
34
35    tmp = image_dup(img);
36image_save(tmp, "xanga1.bmp");
37    /* Clean image a bit */
38//    filter_threshold(tmp, 200);
39    filter_contrast(tmp);
40    //filter_detect_lines(tmp);
41image_save(tmp, "xanga2.bmp");
42    fill_white_holes(tmp);
43//    filter_fill_holes(tmp);
44    filter_smooth(tmp);
45    //filter_median(tmp);
46image_save(tmp, "xanga3.bmp");
47    //filter_detect_lines(tmp);
48//    filter_median(tmp);
49//image_save(tmp, "xanga4.bmp");
50//    filter_threshold(tmp, 128);
51    filter_contrast(tmp);
52image_save(tmp, "xanga4.bmp");
53
54#if 0
55    /* Detect small objects to guess image orientation */
56    filter_median(tmp);
57    filter_threshold(tmp, 200);
58
59    /* Invert rotation and find glyphs */
60    filter_median(tmp);
61#endif
62    find_glyphs(tmp);
63image_save(tmp, "xanga5.bmp");
64
65    /* Clean up our mess */
66    image_free(tmp);
67
68    /* aaaaaaa means decoding failed */
69    if(!strcmp(result, "aaaaaaa"))
70        result[0] = '\0';
71
72    return result;
73}
74
75/* The following functions are local */
76
77static void fill_white_holes(struct image *img)
78{
79    struct image *tmp;
80    int x, y;
81    int r, g, b;
82
83    tmp = image_new(img->width, img->height);
84
85    for(y = 0; y < img->height; y++)
86        for(x = 0; x < img->width; x++)
87        {
88            getpixel(img, x, y, &r, &g, &b);
89            setpixel(tmp, x, y, r, g, b);
90        }
91
92    for(y = 1; y < img->height - 1; y++)
93        for(x = 1; x < img->width - 1; x++)
94        {
95            int count = 0;
96            getpixel(img, x, y, &r, &g, &b);
97            if(r <= 16)
98                continue;
99            getpixel(img, x + 1, y, &r, &g, &b);
100            count += r;
101            getpixel(img, x - 1, y, &r, &g, &b);
102            count += r;
103            getpixel(img, x, y + 1, &r, &g, &b);
104            count += r;
105            getpixel(img, x, y - 1, &r, &g, &b);
106            count += r;
107            if(count > 600)
108                continue;
109            setpixel(tmp, x, y, count / 5, count / 5, count / 5);
110        }
111
112    image_swap(tmp, img);
113    image_free(tmp);
114}
115
116static void find_glyphs(struct image *img)
117{
118#define FONTS 6
119    static struct font *fonts[FONTS];
120    static char *files[] =
121    {
122        "x_font_freemonobold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
123        "x_font_freemonobold_24_az.bmp", "abcdefghijklmnopqrstuvwxyz",
124        "x_font_freesansbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
125        //"x_font_freeserifbold_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
126        "x_font_comic_32_az.bmp", "abcdefghijklmnopqrstuvwxyz",
127        "x_font_comic_24_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
128        "x_font_freesansbold_36_az_messed.bmp", "abcdefghijklmnopqrstuvwxyz",
129    };
130    struct image *tmp;
131    int x, y, i = 0, f;
132    int r, g, b;
133    int xmin, xmax, ymin, ymax, cur = 0;
134    int bestdist, bestfont, bestx, besty, bestch;
135
136    for(f = 0; f < FONTS; f++)
137    {
138        if(!fonts[f])
139        {
140            fonts[f] = font_load_variable(files[f * 2], files[f * 2 + 1]);
141            if(!fonts[f])
142                exit(1);
143            //filter_smooth(fonts[f]->img);
144            //filter_contrast(fonts[f]->img);
145        }
146    }
147
148    tmp = image_new(img->width, img->height);
149
150    for(y = 0; y < img->height; y++)
151        for(x = 0; x < img->width; x++)
152        {
153            getpixel(img, x, y, &r, &g, &b);
154            setpixel(tmp, x, y, 255, g, 255);
155        }
156
157    while(cur < 6)
158    {
159        /* Try to find 1st letter */
160        bestdist = INT_MAX;
161        for(f = 0; f < FONTS; f++) for(i = 0; i < fonts[f]->size; i++)
162        {
163            int localmin = INT_MAX, localx, localy;
164int sqr;
165            if(fonts[f]->glyphs[i].c == 'l' || fonts[f]->glyphs[i].c == 'z')
166                continue;
167            xmin = fonts[f]->glyphs[i].xmin - 5;
168            ymin = fonts[f]->glyphs[i].ymin - 3;
169            xmax = fonts[f]->glyphs[i].xmax + 5;
170            ymax = fonts[f]->glyphs[i].ymax + 3;
171sqr = sqrt(xmax - xmin);
172            for(y = -15; y < 15; y++)
173                for(x = 22 - (xmax - xmin) / 2 + 25 * cur; x < 28 - (xmax - xmin) / 2 + 25 * cur; x++)
174                {
175                    int z, t, dist;
176                    dist = 0;
177                    for(t = 0; t < ymax - ymin; t++)
178                        for(z = 0; z < xmax - xmin; z++)
179                        {
180                            int r2;
181                            getgray(fonts[f]->img, xmin + z, ymin + t, &r);
182                            getgray(img, x + z, y + t, &r2);
183                            if(r < r2)
184                                dist += (r - r2) * (r - r2);
185                            else
186                                dist += (r - r2) * (r - r2) * 3 / 4;
187                        }
188    //                printf("%i %i -> %i\n", x, y, dist);
189//                    dist /= (xmax - xmin);
190//                    dist = dist / sqrt((ymax - ymin) * (xmax - xmin)) / (xmax - xmin);
191                    dist = dist / (xmax - xmin) / sqr;
192//                    dist = dist * 128 / fonts[f]->glyphs[i].count;
193                    if(dist < localmin)
194                    {
195                        localmin = dist;
196                        localx = x;
197                        localy = y;
198                    }
199                }
200            if(localmin < bestdist)
201            {
202//printf("  bestch is now %i (%c) in font %i\n", i, fonts[f]->glyphs[i].c, f);
203                bestdist = localmin;
204                bestfont = f;
205                bestx = localx;
206                besty = localy;
207                bestch = i;
208            }
209        }
210//printf("%i (%c) in font %i\n", i, fonts[bestfont]->glyphs[bestch].c, bestfont);
211//printf("%i < %i < %i\n", 10 + 25 * cur, bestx, 30 + 25 * cur);
212
213        /* Draw best glyph in picture (debugging purposes) */
214        xmin = fonts[bestfont]->glyphs[bestch].xmin - 5;
215        ymin = fonts[bestfont]->glyphs[bestch].ymin - 3;
216        xmax = fonts[bestfont]->glyphs[bestch].xmax + 5;
217        ymax = fonts[bestfont]->glyphs[bestch].ymax + 3;
218        for(y = 0; y < ymax - ymin; y++)
219            for(x = 0; x < xmax - xmin; x++)
220            {
221                getpixel(fonts[bestfont]->img, xmin + x, ymin + y, &r, &g, &b);
222                if(r > 128) continue;
223                setpixel(tmp, bestx + x, besty + y, r, g, b);
224            }
225
226        result[cur++] = fonts[bestfont]->glyphs[bestch].c;
227    }
228
229    image_swap(img, tmp);
230    image_free(tmp);
231}
232
Note: See TracBrowser for help on using the repository browser.