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

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