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

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