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

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