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

Last change on this file since 423 was 423, checked in by Sam Hocevar, 16 years ago
  • fixed a bug in scode.c that was missing bottom lines
  • work with colour images
  • Property svn:keywords set to Id
File size: 4.7 KB
Line 
1/*
2 * scode.c: decode scode captchas
3 * $Id: scode.c 423 2005-01-05 17:02:53Z 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;
28    struct image *tmp1;
29
30    /* allocate enough place */
31    result = malloc(1024 * sizeof(char));
32
33    tmp1 = filter_dup(img);
34
35    /* Remove border */
36    getpixel(img, 1, 1, &r, &g, &b);
37    for(y = 0; y < img->height; y++)
38    {
39        setpixel(tmp1, 0, y, r, g, b);
40        setpixel(tmp1, img->width - 1, y, r, g, b);
41    }
42
43    for(x = 0; x < img->width; x++)
44    {
45        setpixel(tmp1, x, 0, r, g, b);
46        setpixel(tmp1, x, img->height - 1, r, g, b);
47    }
48
49    /* Detect background: first and last 3 lines */
50    for(i = 0; i < 256; i++)
51        stats[i] = 0;
52
53    for(y = 0; y < 3; y++)
54        for(x = 0; x < img->width; x++)
55        {
56            getpixel(tmp1, x, y, &r, &g, &b);
57            stats[r + g + b]++;
58            getpixel(tmp1, x, img->height - 1 - y, &r, &g, &b);
59            stats[r + g + b]++;
60        }
61
62    /* Set non-background colours to 0 */
63    for(y = 0; y < img->height; y++)
64        for(x = 0; x < img->width; x++)
65        {
66            getpixel(tmp1, x, y, &r, &g, &b);
67            if(stats[r + g + b])
68                setpixel(tmp1, x, y, 255, 255, 255);
69            else
70                setpixel(tmp1, x, y, 0, 0, 0);
71        }
72
73    /* Decode glyphs */
74    for(x = 0; x < img->width; x++)
75    {
76        int found = 0;
77        for(y = 0; y < img->height; y++)
78        {
79            getpixel(tmp1, x, y, &r, &g, &b);
80            if(!r)
81            {
82                found = 1;
83                break;
84            }
85        }
86        if(found && !incell)
87        {
88            incell = 1;
89            xmin = x;
90        }
91        else if(!found && incell)
92        {
93            incell = 0;
94            /* Find glyph */
95            result[cur++] = find_glyph(tmp1, xmin, x);
96        }
97    }
98
99    image_free(tmp1);
100    result[cur] = '\0';
101
102    return result;
103}
104
105static char find_glyph(struct image *img, int xmin, int xmax)
106{
107    int ymin = -1, ymax = -1;
108    int x, y, count = 0;
109    int r, g, b;
110
111    /* Compute vertical bounds of glyph */
112    for(y = 0; y < img->height; y++)
113    {
114        int found = 0;
115        for(x = xmin; x < xmax; x++)
116        {
117            getpixel(img, x, y, &r, &g, &b);
118            if(!r)
119            {
120                found = 1;
121                break;
122            }
123        }
124        if(found)
125        {
126            if(ymin == -1)
127                ymin = y;
128            else
129                ymax = y + 1;
130        }
131    }
132
133    for(x = xmin; x < xmax; x++)
134    {
135        for(y = ymin; y < ymax; y++)
136        {
137            getpixel(img, x, y, &r, &g, &b);
138            if(!r)
139                count += 5 * (y - ymin) ^ 3 * (x - xmin);
140                //count += y - ymin;
141        }
142    }
143
144    switch(count)
145    {
146        /* Scode font */
147        case 778: return '0';
148        case 621: return '1';
149        case 854: return '2';
150        case 784: return '3';
151        case 766: return '4';
152        case 771: return '5';
153        case 976: return '6';
154        case 585: return '7';
155        case 980: return '8';
156        case 896: return '9';
157        /* Small font */
158        case 584: return '0';
159        case 454: return '1';
160        case 517: return '2';
161        case 447: return '3';
162        case 469: return '4';
163        case 472: return '5';
164        case 564: return '6';
165        case 298: return '7';
166        case 560: return '8';
167        case 536: return '9';
168        /* Thin font */
169        case 438: return '0';
170        case 405: return '1';
171        case 485: return '2';
172        case 486: return '3';
173        case 413: return '4';
174        case 509: return '5';
175        case 582: return '6';
176        case 242: return '7';
177        case 579: return '8';
178        case 440: return '9';
179#if 0
180        case 162: return '0';
181        case 131: return '1';
182        case 150: return '2';
183        case 139: return '3';
184        case 155: return '4';
185        case 159: return '5';
186        case 181: return '6';
187        case  90: return '7';
188        case 180: return '8';
189        case 170: return '9';
190#endif
191        default:
192            dprintf("don't know about checksum %i\n", count);
193            return '?';
194    }
195}
196
Note: See TracBrowser for help on using the repository browser.