source: pwntcha/trunk/src/filters.c @ 402

Last change on this file since 402 was 402, checked in by Sam Hocevar, 16 years ago
  • print colour count in debug messages
  • Property svn:keywords set to Id
File size: 9.3 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filters.c 402 2005-01-04 02:59:22Z 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#include <math.h>
16
17#include "config.h"
18#include "common.h"
19
20/* Our macros */
21#define FACTOR 1
22//#define FONTNAME "share/font.png" // use with FACTOR = 2
23//#define FONTNAME "share/font_dilated.png" // use with FACTOR = 2
24#define FONTNAME "share/font_dilated_half.png" // use with FACTOR = 1
25
26/* Functions */
27void filter_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        filter_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        filter_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        filter_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        filter_flood_fill(img, x, y - 1, r, g, b);
53}
54
55struct image *filter_dup(struct image *img)
56{
57    struct image *dst;
58    int x, y;
59    int r, g, b;
60
61    dst = image_new(img->width, img->height);
62
63    for(y = 0; y < img->height; y++)
64        for(x = 0; x < img->width; x++)
65        {
66            getpixel(img, x, y, &r, &g, &b);
67            setpixel(dst, x, y, r, g, b);
68        }
69
70    return dst;
71}
72
73struct image *filter_fill_holes(struct image *img)
74{
75    struct image *dst;
76    int x, y;
77    int r, g, b;
78
79    dst = image_new(img->width, img->height);
80
81    for(y = 0; y < img->height; y++)
82        for(x = 0; x < img->width; x++)
83        {
84            getpixel(img, x, y, &r, &g, &b);
85            setpixel(dst, x, y, r, g, b);
86        }
87
88    for(y = 0; y < dst->height; y++)
89        for(x = 2; x < dst->width - 2; x++)
90        {
91            int c1, c2, c3, c4, c5;
92            getpixel(img, x-2, y, &c1, &g, &b);
93            getpixel(img, x-1, y, &c2, &g, &b);
94            getpixel(img, x, y, &c3, &g, &b);
95            getpixel(img, x+1, y, &c4, &g, &b);
96            getpixel(img, x+2, y, &c5, &g, &b);
97            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
98                c3 = (c1 + c2 + c4) / 3;
99            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
100                c3 = (c2 + c4 + c5) / 3;
101            setpixel(dst, x, y, c3, c3, c3);
102        }
103
104    for(x = 0; x < dst->width; x++)
105        for(y = 2; y < dst->height - 2; y++)
106        {
107            int c1, c2, c3, c4, c5;
108            getpixel(img, x, y-2, &c1, &g, &b);
109            getpixel(img, x, y-1, &c2, &g, &b);
110            getpixel(img, x, y, &c3, &g, &b);
111            getpixel(img, x, y+1, &c4, &g, &b);
112            getpixel(img, x, y+2, &c5, &g, &b);
113            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
114                c3 = (c1 + c2 + c4) / 3;
115            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
116                c3 = (c2 + c4 + c5) / 3;
117            setpixel(dst, x, y, c3, c3, c3);
118        }
119
120    return dst;
121}
122
123struct image *filter_detect_lines(struct image *img)
124{
125    struct image *dst;
126    int x, y;
127    int r, ra, rb, g, b;
128
129    dst = image_new(img->width, img->height);
130
131    /* Remove white lines */
132    for(y = 0; y < img->height; y++)
133        for(x = 0; x < img->width; x++)
134        {
135            getpixel(img, x, y, &r, &g, &b);
136            setpixel(dst, x, y, r, g, b);
137            if(y > 0 && y < img->height - 1)
138            {
139                getpixel(img, x, y - 1, &ra, &g, &b);
140                getpixel(img, x, y + 1, &rb, &g, &b);
141                if(r > ra && (r - ra) * (r - rb) > 5000)
142                    setpixel(dst, x, y, ra, ra, ra);
143            }
144        }
145
146    /* Remove black lines */
147    for(y = 0; y < img->height; y++)
148        for(x = 0; x < img->width; x++)
149        {
150            getpixel(dst, x, y, &r, &g, &b);
151            if(y > 0 && y < img->height - 1)
152            {
153                getpixel(img, x, y - 1, &ra, &g, &b);
154                getpixel(img, x, y + 1, &rb, &g, &b);
155                if(r < ra && (r - ra) * (r - rb) > 500)
156                    setpixel(dst, x, y, ra, ra, ra);
157            }
158        }
159
160    return dst;
161}
162
163struct image *filter_equalize(struct image *img, int threshold)
164{
165    struct image *dst;
166    int x, y;
167    int r, g, b;
168
169    dst = image_new(img->width, img->height);
170
171    for(y = 0; y < img->height; y++)
172        for(x = 0; x < img->width; x++)
173        {
174            getpixel(img, x, y, &r, &g, &b);
175            if(r < threshold) r = 0; else r = 255;
176            setpixel(dst, x, y, r, r, r);
177        }
178
179    return dst;
180}
181
182struct image *filter_trick(struct image *img)
183{
184#define TSIZE 3
185    struct image *dst;
186    int x, y, i, j, val, m, more, l, less;
187    int r, g, b;
188
189    dst = image_new(img->width, img->height);
190
191    for(y = 0; y < img->height; y++)
192        for(x = 0; x < img->width; x++)
193            setpixel(dst, x, y, 255, 255, 255);
194
195    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
196        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
197        {
198            getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
199            m = more = l = less = 0;
200            for(i = 0; i < TSIZE; i++)
201                for(j = 0; j < TSIZE; j++)
202                {
203                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
204                    if(r > val)
205                    {
206                        more += r;
207                        m++;
208                    }
209                    else if(r < val)
210                    {
211                        less += r;
212                        l++;
213                    }
214                }
215
216            if(l >= 6)
217                i = less / l;
218            else if(m >= 6)
219                i = more / m;
220            else
221                i = val;
222            setpixel(dst, x, y, i, i, i);
223        }
224
225    return dst;
226}
227
228struct image *filter_smooth(struct image *img)
229{
230#define SSIZE 3
231    struct image *dst;
232    int x, y, i, j, val;
233    int r, g, b;
234
235    dst = image_new(img->width, img->height);
236
237    for(y = 0; y < img->height; y++)
238        for(x = 0; x < img->width; x++)
239            setpixel(dst, x, y, 255, 255, 255);
240
241    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
242        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
243        {
244            val = 0;
245            for(i = 0; i < SSIZE; i++)
246                for(j = 0; j < SSIZE; j++)
247                {
248                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
249                    val += r;
250                }
251
252            i = val / (SSIZE * SSIZE);
253            setpixel(dst, x, y, i, i, i);
254        }
255
256    return dst;
257}
258
259struct image *filter_median(struct image *img)
260{
261#define MSIZE 3
262    struct image *dst;
263    int x, y, i, j, val[MSIZE*MSIZE];
264    int r, g, b;
265
266    dst = image_new(img->width, img->height);
267
268    for(y = 0; y < img->height; y++)
269        for(x = 0; x < img->width; x++)
270            setpixel(dst, x, y, 255, 255, 255);
271
272    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
273        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
274        {
275            for(i = 0; i < MSIZE; i++)
276                for(j = 0; j < MSIZE; j++)
277                {
278                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
279                    val[i * MSIZE + j] = r;
280                }
281
282            /* Bubble sort power! */
283            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
284                for(j = i + 1; j < MSIZE * MSIZE; j++)
285                    if(val[i] > val[j])
286                    {
287                        register int k = val[i];
288                        val[i] = val[j];
289                        val[j] = k;
290                    }
291
292            i = val[MSIZE * MSIZE / 2];
293            setpixel(dst, x, y, i, i, i);
294        }
295
296    return dst;
297}
298
299struct image *filter_contrast(struct image *img)
300{
301    struct image *dst;
302    int histo[256];
303    int x, y, i, min = 255, max = 0;
304    int r, g, b;
305
306    dst = image_new(img->width, img->height);
307
308    for(y = 0; y < img->height; y++)
309        for(x = 0; x < img->width; x++)
310        {
311            getgray(img, x, y, &r);
312            if(r < min) min = r;
313            if(r > max) max = r;
314        }
315
316    if(min == max)
317        histo[min] = 127;
318    else
319        for(i = min; i < max; i++)
320            histo[i] = (i - min) * 255 / (max - min);
321
322    for(y = 0; y < img->height; y++)
323        for(x = 0; x < img->width; x++)
324        {
325            getgray(img, x, y, &r);
326            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
327        }
328
329    return dst;
330}
331
332int filter_count(struct image *img)
333{
334    int histo[256];
335    int x, y, i, count = 0;
336    int r, g, b;
337
338    for(i = 0; i < 256; i++)
339        histo[i] = 0;
340
341    for(y = 0; y < img->height; y++)
342        for(x = 0; x < img->width; x++)
343        {
344            getgray(img, x, y, &r);
345            histo[r] = 1;
346        }
347
348    for(i = 0; i < 256; i++)
349        count += histo[i];
350
351    return count;
352}
353
Note: See TracBrowser for help on using the repository browser.