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

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