source: pwntcha/trunk/src/linuxfr.c @ 420

Last change on this file since 420 was 420, checked in by Sam Hocevar, 16 years ago
  • bugfixes in the linuxfr captcha decoder, and new control.txt
  • Property svn:keywords set to Id
File size: 4.2 KB
Line 
1/*
2 * linuxfr.c: decode linuxfr.org captchas
3 * $Id: linuxfr.c 420 2005-01-04 23:38:10Z 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
17#include "config.h"
18#include "common.h"
19
20#define FONTNAME "share/font_linuxfr.png"
21
22/* Main function */
23char *decode_linuxfr(struct image *img)
24{
25    char all[] = "abcdefghijklmnopqrstuvwxyz"
26                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
27                 "0123456789";
28    char *result;
29    struct image *tmp, *font;
30    int x, y, r, g, b, i, j, c;
31    int stats[40];
32
33    font = image_load(FONTNAME);
34    if(!font)
35    {
36        fprintf(stderr, "cannot load font %s\n", FONTNAME);
37        exit(-1);
38    }
39
40    /* linuxfr captchas have 7 characters */
41    result = malloc(8 * sizeof(char));
42    memset(result, '\0', 8);
43
44    tmp = filter_equalize(img, 150);
45
46    for(y = 0; y < img->height; y++)
47    {
48        int count = 0;
49        for(x = 0; x < img->width; x++)
50        {
51            getpixel(tmp, x, y, &r, &g, &b);
52            if(r == 0)
53                count++;
54        }
55        stats[y] = count;
56    }
57
58    /* Find 7 consecutive lines that have at least 14 pixels; they're
59     * baseline candidates */
60    for(y = 0; y < img->height - 11; y++)
61    {
62        int ycan = 1;
63        for(j = 3; j < 10; j++)
64        {
65            if(stats[y + j] < 14)
66            {
67                ycan = 0;
68                y = y + j - 3;
69                break;
70            }
71        }
72        if(!ycan)
73            continue;
74
75        /* Find 7 consecutive cells that have at least 2 pixels on
76         * each line; they're base column candidates */
77        for(x = 0; x < img->width - 9 * 7 + 1; x++)
78        {
79            int goodx = 1;
80            for(c = 0; c < 7 && goodx; c++)
81            {
82                for(j = 3; j < 10; j++)
83                {
84                    int count = 0;
85                    for(i = 0; i < 8; i++)
86                    {
87                        getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b);
88                        if(r == 0)
89                        {
90                            count++;
91                            if(count == 2)
92                                break;
93                        }
94                    }
95                    if(count < 2)
96                    {
97                        goodx = 0;
98                        break;
99                    }
100                }
101            }
102            if(!goodx)
103                continue;
104
105            /* Now we have an (x,y) candidate - try to fit 7 characters */
106            for(c = 0; c < 7 && goodx; c++)
107            {
108                int r2, g2, b2, ch;
109                int minerror = INT_MAX;
110                for(ch = 0; ch < 62; ch++)
111                {
112                    int error = 0, goodch = 1;
113                    for(j = 0; j < 12 && goodch; j++)
114                        for(i = 0; i < 8; i++)
115                        {
116                            getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b);
117                            getpixel(font, ch * 9 + i, j, &r2, &g2, &b2);
118                            /* Only die if font is black and image is white */
119                            if(r > r2)
120                            {
121                                goodch = 0;
122                                break;
123                            }
124                            else if(r < r2)
125                                error++;
126                        }
127                    if(goodch && error < minerror)
128                    {
129                        minerror = error;
130                        result[c] = all[ch];
131                        result[c+1] = '\0';
132                    }
133                }
134                if(minerror == INT_MAX)
135                    goodx = 0;
136            }
137            /* Wow, that was a good guess! Exit this loop */
138            if(goodx)
139                break;
140        }
141    }
142
143    image_free(tmp);
144    image_free(font);
145
146    if(strlen(result) != 7)
147    {
148        free(result);
149        return NULL;
150    }
151
152    return result;
153}
154
Note: See TracBrowser for help on using the repository browser.