source: pwntcha/trunk/src/scode.c @ 478

Last change on this file since 478 was 478, checked in by Sam Hocevar, 15 years ago
  • support for free.fr pop_hotline pic.
  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1/*
2 * scode.c: decode scode captchas
3 * $Id: scode.c 478 2005-05-09 17:58:06Z sam $
4 *
5 * Copyright: (c) 2004 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
16#include "config.h"
17#include "common.h"
18
19static char find_glyph(struct image *img, int xmin, int xmax);
20
21/* Main function */
22char *decode_scode(struct image *img)
23{
24    char *result;
25    int stats[3 * 256];
26    int x, y, i, incell = 0, cur = 0, xmin = 0;
27    int r, g, b, r2, g2, b2;
28    struct image *tmp1;
29
30    /* allocate enough place */
31    result = malloc(1024 * sizeof(char));
32
33    tmp1 = image_dup(img);
34
35    /* Remove border */
36    getpixel(img, 0, 0, &r2, &g2, &b2);
37    getpixel(img, 1, 1, &r, &g, &b);
38
39    if(r != r2 || g != g2 || b != b2)
40    {
41        for(y = 0; y < img->height; y++)
42        {
43            setpixel(tmp1, 0, y, r, g, b);
44            setpixel(tmp1, img->width - 1, y, r, g, b);
45        }
46
47        for(x = 0; x < img->width; x++)
48        {
49            setpixel(tmp1, x, 0, r, g, b);
50            setpixel(tmp1, x, img->height - 1, r, g, b);
51        }
52    }
53
54    /* Detect background: first and last 3 lines */
55    for(i = 0; i < 3 * 256; i++)
56        stats[i] = 0;
57
58    /* Set (0, 0) colour to background */
59    stats[r2 + g2 + b2] = 1;
60
61    for(y = 0; y < 6; y++)
62    {
63        int y2 = (y & 1) ? img->width - 1 - y / 2 : y / 2;
64        for(x = 0; x < img->width; x++)
65        {
66            getpixel(tmp1, x, y2, &r, &g, &b);
67            if(stats[r + g + b] == 0)
68            {
69                /* Parse middle line to see if this colour can be removed */
70                int available = 0, x2, r2, g2, b2;
71                stats[r + g + b] = 1;
72                for(x2 = 0; x2 < img->width; x2++)
73                {
74                    getpixel(tmp1, x2, img->width / 2, &r2, &g2, &b2);
75                    if(stats[r2 + g2 + b2] == 0)
76                        available = 1;
77                }
78                if(!available)
79                    stats[r + g + b] = 2;
80            }
81        }
82    }
83
84    /* Set non-background colours to 0 */
85    for(y = 0; y < img->height; y++)
86        for(x = 0; x < img->width; x++)
87        {
88            getpixel(tmp1, x, y, &r, &g, &b);
89            if(stats[r + g + b] == 1)
90                setpixel(tmp1, x, y, 255, 255, 255);
91            else
92                setpixel(tmp1, x, y, 0, 0, 0);
93        }
94
95    /* Decode glyphs */
96    for(x = 0; x < img->width; x++)
97    {
98        int found = 0;
99        for(y = 0; y < img->height; y++)
100        {
101            getpixel(tmp1, x, y, &r, &g, &b);
102            if(!r)
103            {
104                found = 1;
105                break;
106            }
107        }
108        if(found && !incell)
109        {
110            incell = 1;
111            xmin = x;
112        }
113        else if(!found && incell)
114        {
115            incell = 0;
116            /* Find glyph */
117            result[cur++] = find_glyph(tmp1, xmin, x);
118        }
119    }
120
121    image_free(tmp1);
122    result[cur] = '\0';
123
124    return result;
125}
126
127static char find_glyph(struct image *img, int xmin, int xmax)
128{
129    int ymin = -1, ymax = -1;
130    int x, y, count = 0;
131    int r, g, b;
132
133    /* Compute vertical bounds of glyph */
134    for(y = 0; y < img->height; y++)
135    {
136        int found = 0;
137        for(x = xmin; x < xmax; x++)
138        {
139            getpixel(img, x, y, &r, &g, &b);
140            if(!r)
141            {
142                found = 1;
143                break;
144            }
145        }
146        if(found)
147        {
148            if(ymin == -1)
149                ymin = y;
150            else
151                ymax = y + 1;
152        }
153    }
154
155    for(x = xmin; x < xmax; x++)
156    {
157        for(y = ymin; y < ymax; y++)
158        {
159            getpixel(img, x, y, &r, &g, &b);
160            if(!r)
161                count += 5 * (y - ymin) ^ 3 * (x - xmin);
162                //count += y - ymin;
163        }
164    }
165
166    switch(count)
167    {
168        /* Scode font */
169        case 778: return '0';
170        case 621: return '1';
171        case 854: return '2';
172        case 784: return '3';
173        case 766: return '4';
174        case 771: return '5';
175        case 976: return '6';
176        case 585: return '7';
177        case 980: return '8';
178        case 896: return '9';
179        /* Small font */
180        case 584: return '0';
181        case 454: return '1';
182        case 517: return '2';
183        case 447: return '3';
184        case 469: return '4';
185        case 472: return '5';
186        case 564: return '6';
187        case 298: return '7';
188        case 560: return '8';
189        case 536: return '9';
190        /* Thin font */
191        case 438: return '0';
192        case 405: return '1';
193        case 485: return '2';
194        case 486: return '3';
195        case 413: return '4';
196        case 509: return '5';
197        case 582: return '6';
198        case 242: return '7';
199        case 579: return '8';
200        case 440: return '9';
201#if 0
202        case 162: return '0';
203        case 131: return '1';
204        case 150: return '2';
205        case 139: return '3';
206        case 155: return '4';
207        case 159: return '5';
208        case 181: return '6';
209        case  90: return '7';
210        case 180: return '8';
211        case 170: return '9';
212#endif
213        /* ourcolony font */
214        case 4020: return '0';
215        case 1970: return '1';
216        case 4627: return '2';
217        case 4410: return '3';
218        case 4468: return '4';
219        case 4329: return '5';
220        case 4910: return '6';
221        case 2378: return '7';
222        case 5375: return '8';
223        case 4710: return '9';
224        default:
225            dprintf("don't know about checksum %i\n", count);
226            return '?';
227    }
228}
229
Note: See TracBrowser for help on using the repository browser.