source: pwntcha/trunk/src/slashdot.c @ 381

Last change on this file since 381 was 381, checked in by Sam Hocevar, 15 years ago
  • first pwntcha commit!
  • Property svn:keywords set to Id
File size: 17.0 KB
Line 
1
2#include <stdio.h>
3#include <stdint.h>
4#include <stdlib.h>
5
6#include "config.h"
7#include "common.h"
8
9/* Our macros */
10#define FACTOR 1
11//#define FONTNAME "font.png" // use with FACTOR = 2
12//#define FONTNAME "font_dilated.png" // use with FACTOR = 2
13#define FONTNAME "font_dilated_half.png" // use with FACTOR = 1
14
15/* Global stuff */
16char *result;
17
18struct
19{
20    int xmin, ymin, xmax, ymax;
21}
22objlist[100];
23int objects = 0, first = -1, last = -1;
24
25/* Functions */
26
27void flood_fill(struct image *img, int x, int y, int r, int g, int b)
28{
29    int oldr, oldg, oldb;
30    int nextr, nextg, nextb;
31
32    if(x < 0 || y < 0 || x >= img->width || y >= img->height)
33        return;
34
35    getpixel(img, x, y, &oldr, &oldg, &oldb);
36    setpixel(img, x, y, r, g, b);
37
38    getpixel(img, x + 1, y, &nextr, &nextg, &nextb);
39    if(nextr == oldr && nextg == oldg && nextb == oldb)
40        flood_fill(img, x + 1, y, r, g, b);
41
42    getpixel(img, x - 1, y, &nextr, &nextg, &nextb);
43    if(nextr == oldr && nextg == oldg && nextb == oldb)
44        flood_fill(img, x - 1, y, r, g, b);
45
46    getpixel(img, x, y + 1, &nextr, &nextg, &nextb);
47    if(nextr == oldr && nextg == oldg && nextb == oldb)
48        flood_fill(img, x, y + 1, r, g, b);
49
50    getpixel(img, x, y - 1, &nextr, &nextg, &nextb);
51    if(nextr == oldr && nextg == oldg && nextb == oldb)
52        flood_fill(img, x, y - 1, r, g, b);
53}
54
55struct image *count_objects(struct image *img)
56{
57    struct image *dst;
58    int gotblack = 1;
59    int x, y, i;
60    int r, g, b;
61
62    dst = new_image(img->width, img->height);
63
64    for(y = 0; y < img->height; y++)
65        for(x = 0; x < img->width; x++)
66        {
67            getpixel(img, x, y, &r, &g, &b);
68            setpixel(dst, x, y, r, g, b);
69        }
70
71    while(gotblack)
72    {
73        gotblack = 0;
74        for(y = 0; y < dst->height; y++)
75            for(x = 0; x < dst->width; x++)
76            {
77                getpixel(dst, x, y, &r, &g, &b);
78                if(r == 50 && g == 50 && b == 50)
79                {
80                    gotblack = 1;
81                    flood_fill(dst, x, y, 255 - objects, 0, 0);
82                    objects++;
83                }
84            }
85    }
86
87    //printf("%i objects\n", objects);
88
89    for(i = 0; i < objects; i++)
90    {
91        objlist[i].ymin = dst->height;
92        objlist[i].ymax = 0;
93
94        for(y = 0; y < dst->height; y++)
95            for(x = 0; x < dst->width; x++)
96            {
97                getpixel(dst, x, y, &r, &g, &b);
98                if(r == 255 - i && g == 0 && b == 0)
99                {
100                    if(y < objlist[i].ymin) { objlist[i].ymin = y; objlist[i].xmin = x; }
101                    if(y > objlist[i].ymax) { objlist[i].ymax = y; objlist[i].xmax = x; }
102                }
103            }
104        //printf("y min-max: %i %i (size %i)\n", objlist[i].ymin, objlist[i].ymax, objlist[i].ymax - objlist[i].ymin + 1);
105        if(objlist[i].ymax - objlist[i].ymin > 18 && objlist[i].ymax - objlist[i].ymin < 27)
106        {
107            if(first == -1)
108                first = i;
109            last = i;
110            flood_fill(dst, objlist[i].xmin, objlist[i].ymin, 0, 0, 255);
111        }
112    }
113
114#if 0
115    { CvPoint A, B;
116      A.x = (objlist[first].xmin + objlist[first].xmax) / 2;
117      A.y = (objlist[first].ymin + objlist[first].ymax) / 2;
118      B.x = (objlist[last].xmin + objlist[last].xmax) / 2;
119      B.y = (objlist[last].ymin + objlist[last].ymax) / 2;
120      cvLine(dst, A, B, 0, 2.0, 0);
121    }
122#endif
123
124    return dst;
125}
126
127struct image *rotate(struct image *img)
128{
129    struct image *dst;
130    int x, y, xdest, ydest;
131    int r, g, b, R, G, B;
132    int X = objlist[first].xmin - objlist[last].xmin;
133    int Y = objlist[first].ymin - objlist[last].ymin;
134    float xtmp, ytmp;
135    float sina = (1.0 * Y) / sqrt(1.0 * X * X + Y * Y);
136    float cosa = (1.0 * X) / sqrt(1.0 * X * X + Y * Y);
137    if(sina * cosa > 0)
138    {
139        sina = -sina;
140        cosa = -cosa;
141    }
142
143    dst = new_image(img->width * FACTOR, img->height * FACTOR);
144
145    for(y = 0; y < img->height * FACTOR; y++)
146        for(x = 0; x < img->width * FACTOR; x++)
147        {
148            xtmp = 1.0 * (x - img->width * FACTOR / 2) / FACTOR;
149            ytmp = 1.0 * (y - img->height * FACTOR / 2) / FACTOR;
150            xdest = xtmp * cosa - ytmp * sina + 0.5 * img->width;
151            ydest = ytmp * cosa + xtmp * sina + 0.5 * img->height;
152            //R = G = B = 0;
153            getpixel(img, xdest, ydest, &r, &g, &b);
154            //R += r; G += g; B += b;
155            //getpixel(img, xdest+1, ydest, &r, &g, &b);
156            //R += r; G += g; B += b;
157            //getpixel(img, xdest, ydest+1, &r, &g, &b);
158            //R += r; G += g; B += b;
159            //getpixel(img, xdest+1, ydest+1, &r, &g, &b);
160            //R += r; G += g; B += b;
161            //r = R / 4; g = G / 4; b = B / 4;
162            if(r == 255 && g == 0 && b == 255)
163                g = 255;
164            setpixel(dst, x, y, r, g, b);
165        }
166
167    return dst;
168}
169
170struct image *fill_holes(struct image *img)
171{
172    struct image *dst;
173    int x, y;
174    int r, g, b;
175
176    dst = new_image(img->width, img->height);
177
178    for(y = 0; y < img->height; y++)
179        for(x = 0; x < img->width; x++)
180        {
181            getpixel(img, x, y, &r, &g, &b);
182            setpixel(dst, x, y, r, g, b);
183        }
184
185    for(y = 0; y < dst->height; y++)
186        for(x = 2; x < dst->width - 2; x++)
187        {
188            int c1, c2, c3, c4, c5;
189            getpixel(img, x-2, y, &c1, &g, &b);
190            getpixel(img, x-1, y, &c2, &g, &b);
191            getpixel(img, x, y, &c3, &g, &b);
192            getpixel(img, x+1, y, &c4, &g, &b);
193            getpixel(img, x+2, y, &c5, &g, &b);
194            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
195                c3 = (c1 + c2 + c4) / 3;
196            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
197                c3 = (c2 + c4 + c5) / 3;
198            setpixel(dst, x, y, c3, c3, c3);
199        }
200
201    for(x = 0; x < dst->width; x++)
202        for(y = 2; y < dst->height - 2; y++)
203        {
204            int c1, c2, c3, c4, c5;
205            getpixel(img, x, y-2, &c1, &g, &b);
206            getpixel(img, x, y-1, &c2, &g, &b);
207            getpixel(img, x, y, &c3, &g, &b);
208            getpixel(img, x, y+1, &c4, &g, &b);
209            getpixel(img, x, y+2, &c5, &g, &b);
210            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
211                c3 = (c1 + c2 + c4) / 3;
212            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
213                c3 = (c2 + c4 + c5) / 3;
214            setpixel(dst, x, y, c3, c3, c3);
215        }
216
217    return dst;
218}
219
220struct image *cut_cells(struct image *img)
221{
222    struct image *dst;
223    int x, y;
224    int r, g, b;
225
226    dst = new_image(img->width, img->height);
227
228    for(y = 0; y < img->height; y++)
229        for(x = 0; x < img->width; x++)
230        {
231            getpixel(img, x, y, &r, &g, &b);
232            setpixel(dst, x, y, r, g, b);
233        }
234
235    for(x = 0; x < img->width; x++)
236    {
237        setpixel(dst, x, 0, 255, 255, 255);
238        setpixel(dst, x, img->height - 1, 255, 255, 255);
239    }
240
241    for(y = 0; y < img->height; y++)
242        for(x = 0; x < 7; x++)
243        {
244            setpixel(dst, x * img->width / 7, y, 255, 255, 255);
245            setpixel(dst, (x + 1) * img->width / 7 - 1, y, 255, 255, 255);
246        }
247
248    return dst;
249}
250
251struct image *detect_lines(struct image *img)
252{
253    struct image *dst;
254    int x, y;
255    int r, ra, rb, g, b;
256
257    dst = new_image(img->width, img->height);
258
259    /* Remove white lines */
260    for(y = 0; y < img->height; y++)
261        for(x = 0; x < img->width; x++)
262        {
263            getpixel(img, x, y, &r, &g, &b);
264            setpixel(dst, x, y, r, g, b);
265#if 1
266            if(y > 0 && y < img->height - 1)
267            {
268                getpixel(img, x, y - 1, &ra, &g, &b);
269                getpixel(img, x, y + 1, &rb, &g, &b);
270                if(r > ra && (r - ra) * (r - rb) > 5000)
271                    setpixel(dst, x, y, ra, ra, ra);
272            }
273#endif
274        }
275
276    /* Remove black lines */
277    for(y = 0; y < img->height; y++)
278        for(x = 0; x < img->width; x++)
279        {
280            getpixel(dst, x, y, &r, &g, &b);
281            if(y > 0 && y < img->height - 1)
282            {
283                getpixel(img, x, y - 1, &ra, &g, &b);
284                getpixel(img, x, y + 1, &rb, &g, &b);
285                if(r < ra && (r - ra) * (r - rb) > 500)
286                    setpixel(dst, x, y, ra, ra, ra);
287            }
288        }
289
290    return dst;
291}
292
293struct image *equalize(struct image *img)
294{
295    struct image *dst;
296    int x, y;
297    int r, g, b;
298
299    dst = new_image(img->width, img->height);
300
301    for(y = 0; y < img->height; y++)
302        for(x = 0; x < img->width; x++)
303        {
304            getpixel(img, x, y, &r, &g, &b);
305            if(r < 200) r = 50; else r = 200;
306            setpixel(dst, x, y, r, r, r);
307        }
308
309    return dst;
310}
311
312struct image *trick(struct image *img)
313{
314#define TSIZE 3
315    struct image *dst;
316    int x, y, i, j, val, m, more, l, less;
317    int r, g, b;
318
319    dst = new_image(img->width, img->height);
320
321    for(y = 0; y < img->height; y++)
322        for(x = 0; x < img->width; x++)
323            setpixel(dst, x, y, 255, 255, 255);
324
325    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
326        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
327        {
328            getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &val, &g, &b);
329            m = more = l = less = 0;
330            for(i = 0; i < TSIZE; i++)
331                for(j = 0; j < TSIZE; j++)
332                {
333                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
334                    if(r > val)
335                    {
336                        more += r;
337                        m++;
338                    }
339                    else if(r < val)
340                    {
341                        less += r;
342                        l++;
343                    }
344                }
345
346            if(l >= 6)
347                i = less / l;
348            else if(m >= 6)
349                i = more / m;
350            else
351                i = val;
352            setpixel(dst, x, y, i, i, i);
353        }
354
355    return dst;
356}
357
358struct image *smooth(struct image *img)
359{
360#define SSIZE 3
361    struct image *dst;
362    int x, y, i, j, val;
363    int r, g, b;
364
365    dst = new_image(img->width, img->height);
366
367    for(y = 0; y < img->height; y++)
368        for(x = 0; x < img->width; x++)
369            setpixel(dst, x, y, 255, 255, 255);
370return dst;
371
372    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
373        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
374        {
375            val = 0;
376            for(i = 0; i < SSIZE; i++)
377                for(j = 0; j < SSIZE; j++)
378                {
379                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
380                    val += r;
381                }
382
383            i = val / (SSIZE * SSIZE);
384            setpixel(dst, x, y, i, i, i);
385        }
386
387    return dst;
388}
389
390struct image *median(struct image *img)
391{
392#define MSIZE 4
393    struct image *dst;
394    int x, y, i, j, val[MSIZE*MSIZE];
395    int r, g, b;
396
397    dst = new_image(img->width, img->height);
398
399    for(y = 0; y < img->height; y++)
400        for(x = 0; x < img->width; x++)
401            setpixel(dst, x, y, 255, 255, 255);
402
403    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
404        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
405        {
406            for(i = 0; i < MSIZE; i++)
407                for(j = 0; j < MSIZE; j++)
408                {
409                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
410                    val[i * MSIZE + j] = r;
411                }
412
413            /* Bubble sort power! */
414            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
415                for(j = i + 1; j < MSIZE * MSIZE; j++)
416                    if(val[i] > val[j])
417                    {
418                        register int k = val[i];
419                        val[i] = val[j];
420                        val[j] = k;
421                    }
422
423            i = val[MSIZE * MSIZE / 2];
424            setpixel(dst, x, y, i, i, i);
425        }
426
427    return dst;
428}
429
430struct image * find_glyphs(struct image *img)
431{
432    char all[] = "abcdefgijkmnpqrstvwxyz";
433    struct
434    {
435        int xmin, xmax, ymin, ymax;
436        int count;
437    }
438    glyphs[22];
439    struct image *dst;
440    struct image *font = load_image(FONTNAME);
441    int x, y, i = 0;
442    int r, g, b, r2, g2, b2;
443    int xmin, xmax, ymin, ymax, incell = 0, count = 0, startx = 0, cur = 0;
444    int distmin, distx, disty, distch;
445
446    if(!font)
447    {
448        fprintf(stderr, "cannot load font %s\n", FONTNAME);
449        exit(-1);
450    }
451
452    dst = new_image(img->width, img->height);
453
454    for(y = 0; y < img->height; y++)
455        for(x = 0; x < img->width; x++)
456        {
457            getpixel(img, x, y, &r, &g, &b);
458            setpixel(dst, x, y, 255, g, 255);
459        }
460
461    strcpy(result, "       ");
462
463    for(x = 0; x < font->width; x++)
464    {
465        int found = 0;
466        for(y = 0; y < font->height; y++)
467        {
468            getpixel(font, x, y, &r, &g, &b);
469            if(r < 128)
470            {
471                found = 1;
472                count += (255 - r);
473            }
474        }
475        if(found && !incell)
476        {
477            incell = 1;
478            xmin = x;
479        }
480        else if(!found && incell)
481        {
482            incell = 0;
483            xmax = x;
484#if 0
485            ymin = font->height;
486            ymax = 0;
487            for(y = 0; y < font->height; y++)
488            {
489                int newx;
490                int gotit = 0;
491                for(newx = xmin; newx < xmax; newx++)
492                {
493                    getpixel(font, newx, y, &r, &g, &b);
494                    if(r < 128)
495                    {
496                        gotit = 1;
497                        break;
498                    }
499                }
500                if(gotit)
501                {
502                    if(ymin > y) ymin = y;
503                    if(ymax <= y) ymax = y + 1;
504                }
505            }
506#else
507            ymin = 0;
508            ymax = font->height;
509#endif
510            glyphs[i].xmin = xmin;
511            glyphs[i].xmax = xmax;
512            glyphs[i].ymin = ymin;
513            glyphs[i].ymax = ymax;
514            glyphs[i].count = count;
515            count = 0;
516            i++;
517        }
518    }
519
520    if(i != 22)
521    {
522        printf("error: could not find 22 glyphs in font\n");
523        exit(-1);
524    }
525
526while(cur < 7)
527{
528    /* Try to find 1st letter */
529    distmin = 999999999;
530    for(i = 0; i < 22; i++)
531    {
532        int localmin = 99999999, localx, localy;
533//if(all[i] == 'i') continue;
534        xmin = glyphs[i].xmin;
535        ymin = glyphs[i].ymin;
536        xmax = glyphs[i].xmax;
537        ymax = glyphs[i].ymax;
538        //printf("trying to find %c (%i×%i) - ", all[i], xmax - xmin, ymax - ymin);
539        for(y = -5 * FACTOR; y < 5 * FACTOR; y++)
540            for(x = startx - 5 * FACTOR; x < startx + 5 * FACTOR; x++)
541            {
542                int z, t, dist;
543                dist = 0;
544                for(t = 0; t < ymax - ymin; t++)
545                    for(z = 0; z < xmax - xmin; z++)
546                    {
547                        getgray(font, xmin + z, ymin + t, &r);
548                        getgray(img, x + z, y + t, &r2);
549                        dist += abs(r - r2);
550                    }
551//                printf("%i %i -> %i\n", x, y, dist);
552                //dist /= sqrt(xmax - xmin);
553                dist = dist * 128 / glyphs[i].count;
554                if(dist < localmin)
555                {
556                    localmin = dist;
557                    localx = x;
558                    localy = y;
559                }
560            }
561        //fprintf(stderr, "%i (%i,%i)\n", localmin, localx - startx, localy);
562        if(localmin < distmin)
563        {
564            distmin = localmin;
565            distx = localx;
566            disty = localy;
567            distch = i;
568        }
569    }
570
571    //fprintf(stderr, "%i (%i,%i)\n", distmin, distx - startx, disty);
572    //printf("min diff: %c - %i (%i, %i)\n", all[distch], distmin, distx, disty);
573
574    /* Print min glyph */
575    xmin = glyphs[distch].xmin;
576    ymin = glyphs[distch].ymin;
577    xmax = glyphs[distch].xmax;
578    ymax = glyphs[distch].ymax;
579    for(y = 0; y < ymax - ymin; y++)
580        for(x = 0; x < xmax - xmin; x++)
581        {
582            getpixel(font, xmin + x, ymin + y, &r, &g, &b);
583            if(r > 128) continue;
584            setpixel(dst, distx + x, disty + y, r, g, b);
585        }
586
587    startx = distx + xmax - xmin;
588    result[cur++] = all[distch];
589}
590
591    return dst;
592}
593
594char * slashdot_decode(char *image)
595{
596    struct image *img, *tmp, *tmp2, *dst;
597
598    img = load_image(image);
599    if(img == NULL)
600        return NULL;
601
602    result = malloc(8 * sizeof(char));
603//    display(img);
604
605//    tmp = equalize(img);
606//    display(tmp);
607//    tmp = fill_holes(tmp);
608//    display(tmp);
609
610//    dst = median(tmp);
611tmp = smooth(img);
612tmp = fill_holes(img);
613tmp = median(tmp);
614//tmp = smooth(tmp);
615//display(tmp);
616//tmp = trick(tmp);
617//display(tmp);
618tmp = equalize(tmp);
619//display(tmp);
620
621tmp = detect_lines(img);
622tmp = fill_holes(tmp);
623//tmp = cut_cells(tmp);
624//display_image(tmp);
625
626tmp2 = median(tmp);
627tmp2 = equalize(tmp2);
628count_objects(tmp2);
629//display_image(tmp2);
630
631//tmp = median(tmp);
632tmp = rotate(tmp);
633tmp = median(tmp);
634//display_image(tmp);
635//tmp = equalize(tmp);
636//tmp = cut_cells(tmp);
637//        cvSaveImage(argv[2], tmp);
638
639tmp = find_glyphs(tmp);
640//display_image(tmp);
641
642//        cvSaveImage(argv[3], tmp);
643
644    return result;
645}
646
Note: See TracBrowser for help on using the repository browser.