| [426] | 1 | /* |
|---|
| 2 | * clubic.c: decode clubic captchas |
|---|
| 3 | * $Id$ |
|---|
| 4 | * |
|---|
| 5 | * Copyright: (c) 2005 Sam Hocevar <sam@zoy.org> |
|---|
| [2315] | 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. |
|---|
| [426] | 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 | |
|---|
| [445] | 21 | static void find_glyphs(struct image *img); |
|---|
| [426] | 22 | |
|---|
| 23 | /* Our macros */ |
|---|
| 24 | char *result; |
|---|
| 25 | |
|---|
| 26 | /* Main function */ |
|---|
| 27 | char *decode_clubic(struct image *img) |
|---|
| 28 | { |
|---|
| [445] | 29 | struct image *tmp; |
|---|
| [426] | 30 | |
|---|
| 31 | /* clubic captchas have 6 characters */ |
|---|
| 32 | result = malloc(7 * sizeof(char)); |
|---|
| 33 | strcpy(result, " "); |
|---|
| 34 | |
|---|
| [445] | 35 | tmp = image_dup(img); |
|---|
| [482] | 36 | filter_threshold(tmp, 200); |
|---|
| [445] | 37 | find_glyphs(tmp); |
|---|
| [426] | 38 | |
|---|
| [445] | 39 | image_free(tmp); |
|---|
| [426] | 40 | |
|---|
| 41 | return result; |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| [445] | 44 | static void find_glyphs(struct image *img) |
|---|
| [426] | 45 | { |
|---|
| [448] | 46 | static struct font *font = NULL; |
|---|
| [445] | 47 | struct image *tmp; |
|---|
| [426] | 48 | int x, y, i = 0; |
|---|
| 49 | int r, g, b; |
|---|
| [448] | 50 | int xmin, xmax, ymin, ymax, startx = 0, cur = 0; |
|---|
| [426] | 51 | int distmin, distx, disty, distch; |
|---|
| 52 | |
|---|
| [448] | 53 | if(!font) |
|---|
| 54 | { |
|---|
| 55 | font = font_load_variable("font_clubic.png", "0123456789"); |
|---|
| 56 | if(!font) |
|---|
| 57 | exit(1); |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| [445] | 60 | tmp = image_new(img->width, img->height); |
|---|
| [426] | 61 | |
|---|
| 62 | for(y = 0; y < img->height; y++) |
|---|
| 63 | for(x = 0; x < img->width; x++) |
|---|
| 64 | { |
|---|
| 65 | getpixel(img, x, y, &r, &g, &b); |
|---|
| [445] | 66 | setpixel(tmp, x, y, 255, g, 255); |
|---|
| [426] | 67 | } |
|---|
| 68 | |
|---|
| 69 | while(cur < 6) |
|---|
| 70 | { |
|---|
| 71 | /* Try to find 1st letter */ |
|---|
| 72 | distmin = INT_MAX; |
|---|
| [448] | 73 | for(i = 0; i < font->size; i++) |
|---|
| [426] | 74 | { |
|---|
| 75 | int localmin = INT_MAX, localx, localy; |
|---|
| [448] | 76 | xmin = font->glyphs[i].xmin; |
|---|
| 77 | ymin = font->glyphs[i].ymin; |
|---|
| 78 | xmax = font->glyphs[i].xmax; |
|---|
| 79 | ymax = font->glyphs[i].ymax; |
|---|
| [426] | 80 | for(y = -4; y < 4; y++) |
|---|
| 81 | for(x = startx; x < startx + 4; x++) |
|---|
| 82 | { |
|---|
| 83 | int z, t, dist; |
|---|
| 84 | dist = 0; |
|---|
| 85 | for(t = 0; t < ymax - ymin; t++) |
|---|
| 86 | for(z = 0; z < xmax - xmin; z++) |
|---|
| 87 | { |
|---|
| 88 | int r2; |
|---|
| [448] | 89 | getgray(font->img, xmin + z, ymin + t, &r); |
|---|
| [426] | 90 | getgray(img, x + z, y + t, &r2); |
|---|
| 91 | dist += abs(r - r2); |
|---|
| 92 | } |
|---|
| [448] | 93 | dist = dist * 128 / font->glyphs[i].count; |
|---|
| [426] | 94 | if(dist < localmin) |
|---|
| 95 | { |
|---|
| 96 | localmin = dist; |
|---|
| 97 | localx = x; |
|---|
| 98 | localy = y; |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | if(localmin < distmin) |
|---|
| 102 | { |
|---|
| 103 | distmin = localmin; |
|---|
| 104 | distx = localx; |
|---|
| 105 | disty = localy; |
|---|
| 106 | distch = i; |
|---|
| 107 | } |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | /* Print min glyph */ |
|---|
| [448] | 111 | xmin = font->glyphs[distch].xmin; |
|---|
| 112 | ymin = font->glyphs[distch].ymin; |
|---|
| 113 | xmax = font->glyphs[distch].xmax; |
|---|
| 114 | ymax = font->glyphs[distch].ymax; |
|---|
| [426] | 115 | for(y = 0; y < ymax - ymin; y++) |
|---|
| 116 | for(x = 0; x < xmax - xmin; x++) |
|---|
| 117 | { |
|---|
| [448] | 118 | getpixel(font->img, xmin + x, ymin + y, &r, &g, &b); |
|---|
| 119 | if(r > 128) |
|---|
| 120 | continue; |
|---|
| [445] | 121 | setpixel(tmp, distx + x, disty + y, r, g, b); |
|---|
| [426] | 122 | } |
|---|
| 123 | |
|---|
| 124 | startx = distx + xmax - xmin; |
|---|
| [448] | 125 | result[cur++] = font->glyphs[distch].c; |
|---|
| [426] | 126 | } |
|---|
| 127 | |
|---|
| [445] | 128 | image_free(tmp); |
|---|
| [426] | 129 | } |
|---|
| 130 | |
|---|