source: pwntcha/trunk/src/ticketmaster/decoder.c @ 2317

Last change on this file since 2317 was 2317, checked in by Sam Hocevar, 12 years ago
  • Preparing a huge PWNtcha reorganisation. First step: put each decoder in its own subdirectory.
  • Property svn:keywords set to Id
File size: 5.2 KB
Line 
1/*
2 * ticketmaster.c: decode ticketmaster captchas
3 * $Id: decoder.c 2317 2008-04-26 08:41:35Z sam $
4 *
5 * Copyright: (c) 2006 Sam Hocevar <sam@zoy.org>
6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <limits.h>
17
18#include "config.h"
19#include "common.h"
20
21#define WIDTH 290
22#define HEIGHT 80
23
24int grid_y[HEIGHT], grid_x[WIDTH];
25
26int dx_top[WIDTH], dy_top[WIDTH];
27int dx_bottom[WIDTH], dy_bottom[WIDTH];
28
29int perturbation_color(struct image *img, int x, int y);
30int real_color(struct image *img, int x, int y);
31
32int detect_grid(struct image *img);
33int detect_lines(struct image *img, int top);
34
35static inline int fastgetgray(struct image *img, int x, int y)
36{
37    int r, g, b;
38    getpixel(img, x, y, &r, &g, &b);
39    return (r + g + b + 1) / 3;
40}
41
42/* Main function */
43char *decode_ticketmaster(struct image *img)
44{
45    struct image *tmp;
46    int x, y;
47
48    if(detect_grid(img))
49        pwnprint("image has vertical grid\n");
50
51    detect_lines(img, 1);
52    detect_lines(img, 0);
53
54    tmp = image_dup(img);
55
56    /* Remove perturbations */
57    for(y = 1; y < HEIGHT - 1; y++)
58    {
59        for(x = 1; x < WIDTH - 1; x++)
60        {
61            int i, j, ok = 1;
62
63            if(perturbation_color(img, x, y) != 0)
64                continue;
65
66            for(j = -1; j <= 1; j++)
67            {
68                for(i = -1; i <= 1; i++)
69                {
70                    if(i == 0 && j == 0)
71                        continue;
72
73                    if(real_color(img, x + i, y + j)
74                         != perturbation_color(img, x + i, y + j))
75                        goto lol;
76                }
77            }
78
79            if(!ok)
80                continue;
81
82            setpixel(tmp, x, y, 255, 255, 255);
83
84lol: continue;
85        }
86    }
87
88    /* Lol, display lines */
89    for(x = 1; x < WIDTH - 1; x++)
90    {
91        if(dy_top[x])
92            for(y = 0; y < HEIGHT; y++)
93            {
94                int newx = (x * 1024 + dx_top[x] + (y * dy_top[x])) / 1024;
95                setpixel(tmp, newx, y, 0, 255, 0);
96            }
97
98        if(dy_bottom[x])
99            for(y = 0; y < HEIGHT; y++)
100            {
101                int newx = (x * 1024 + dx_bottom[x] + (y * dy_bottom[x])) / 1024;
102                setpixel(tmp, newx, (HEIGHT - y - 1), 0, 255, 0);
103            }
104    }
105
106image_save(tmp, "ticketmaster-output.bmp");
107    image_free(tmp);
108
109    return strdup("lol");
110}
111
112int real_color(struct image *img, int x, int y)
113{
114    return fastgetgray(img, x, y) < 40 ? 0 : 255;
115}
116
117int perturbation_color(struct image *img, int x, int y)
118{
119    if(grid_x[x]) return 0;
120
121    if(grid_y[y]) return 0;
122
123    return 255;
124}
125
126int detect_lines(struct image *img, int top)
127{
128    int x, y, i, j;
129
130    int dx, dy;
131    int *mydx, *mydy;
132
133    if(top)
134    {
135        mydx = dx_top;
136        mydy = dy_top;
137    }
138    else
139    {
140        mydx = dx_bottom;
141        mydy = dy_bottom;
142    }
143
144    /* Detect top-bottom line candidates */
145    for(x = 0; x < WIDTH; x++)
146    {
147        int candidate = 0, worstmissed;
148
149        y = top ? 0 : HEIGHT - 3;
150        for(j = 0; j < 3; j++)
151        {
152            for(i = -1; i <= 1; i++)
153            {
154                if(fastgetgray(img, x + i, y + j) < 40)
155                {
156                    candidate++;
157                    break;
158                }
159            }
160        }
161
162        if(candidate < 3)
163            continue;
164
165        mydx[x] = mydy[x] = 0;
166
167        worstmissed = 30;
168
169        /* Refine slope, in 1/1024th of a pixel steps */
170        for(dx = -1024; dx < 1024; dx += 128)
171        {
172            for(dy = 700; dy < 1300; dy += 16)
173            {
174                int missed = 0;
175
176                for(y = 0; y < HEIGHT; y++)
177                {
178                    int newx = (x * 1024 + dx + (y * dy)) / 1024;
179                    int gray = fastgetgray(img, newx, top ? y : (HEIGHT - y - 1));
180
181                    if(gray > 40)
182                    {
183                        missed++;
184
185                        if(missed >= worstmissed)
186                            break;
187                    }
188                }
189
190                if(missed < worstmissed)
191                {
192                    worstmissed = missed;
193                    mydx[x] = dx;
194                    mydy[x] = dy;
195                }
196            }
197        }
198
199        if(worstmissed == 30)
200            continue;
201
202        pwnprint("found a line at %i (+ %i), slope %i/1024\n", x, mydx[x], mydy[x]);
203    }
204
205    return 1;
206}
207
208int detect_grid(struct image *img)
209{
210    int x, y;
211
212    int lines = 0, columns = 0;
213
214    memset(grid_y, 0, sizeof(grid_y));
215    memset(grid_x, 0, sizeof(grid_x));
216
217    for(y = 0; y < HEIGHT; y++)
218    {
219        for(x = 0; x < WIDTH; x++)
220        {
221            if(fastgetgray(img, x, y) < 40)
222            {
223                grid_x[x]++;
224                grid_y[y]++;
225            }
226        }
227    }
228
229    for(y = 0; y < HEIGHT; y++)
230        if((grid_y[y] = (grid_y[y] > WIDTH * 90 / 100))) lines++;
231
232    for(x = 0; x < WIDTH; x++)
233        if((grid_x[x] = (grid_x[x] > HEIGHT * 90 / 100))) columns++;
234
235    return lines * columns > 3 * 20;
236}
237
Note: See TracBrowser for help on using the repository browser.