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

Last change on this file since 416 was 413, checked in by Sam Hocevar, 18 years ago
  • fixed a bug in the SDL code: alpha mask should be set to 0.
  • implemented filter_black_stuff to remove black dots.
  • allow threshold to be negative in filter_equalize; in this case, invert colours.
  • implemented filter_crop.
  • Property svn:keywords set to Id
File size: 11.3 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filters.c 413 2005-01-04 17:06:04Z 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_black_stuff(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 vertical stuff */
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 horizontal stuff */
147    for(y = 0; y < img->height; y++)
148        for(x = 0; x < img->width; x++)
149        {
150            getpixel(img, x, y, &r, &g, &b);
151            if(x > 0 && x < img->width - 1)
152            {
153                getpixel(dst, x - 1, y, &ra, &g, &b);
154                getpixel(dst, x + 1, y, &rb, &g, &b);
155                if(r < ra && (r - ra) * (r - rb) > 5000)
156                    setpixel(dst, x, y, ra, ra, ra);
157            }
158        }
159
160    return dst;
161}
162
163struct image *filter_detect_lines(struct image *img)
164{
165    struct image *dst;
166    int x, y;
167    int r, ra, rb, g, b;
168
169    dst = image_new(img->width, img->height);
170
171    /* Remove white lines */
172    for(y = 0; y < img->height; y++)
173        for(x = 0; x < img->width; x++)
174        {
175            getpixel(img, x, y, &r, &g, &b);
176            setpixel(dst, x, y, r, g, b);
177            if(y > 0 && y < img->height - 1)
178            {
179                getpixel(img, x, y - 1, &ra, &g, &b);
180                getpixel(img, x, y + 1, &rb, &g, &b);
181                if(r > ra && (r - ra) * (r - rb) > 5000)
182                    setpixel(dst, x, y, ra, ra, ra);
183            }
184        }
185
186    /* Remove black lines */
187    for(y = 0; y < img->height; y++)
188        for(x = 0; x < img->width; x++)
189        {
190            getpixel(dst, x, y, &r, &g, &b);
191            if(y > 0 && y < img->height - 1)
192            {
193                getpixel(img, x, y - 1, &ra, &g, &b);
194                getpixel(img, x, y + 1, &rb, &g, &b);
195                if(r < ra && (r - ra) * (r - rb) > 500)
196                    setpixel(dst, x, y, ra, ra, ra);
197            }
198        }
199
200    return dst;
201}
202
203struct image *filter_equalize(struct image *img, int threshold)
204{
205    struct image *dst;
206    int x, y;
207    int r, g, b;
208    int min = 0, max = 255;
209
210    dst = image_new(img->width, img->height);
211
212    if(threshold < 0)
213    {
214        min = 255;
215        max = 0;
216        threshold = -threshold;
217    }
218
219    for(y = 0; y < img->height; y++)
220        for(x = 0; x < img->width; x++)
221        {
222            getpixel(img, x, y, &r, &g, &b);
223            if(r < threshold)
224                setpixel(dst, x, y, min, min, min);
225            else
226                setpixel(dst, x, y, max, max, max);
227        }
228
229    return dst;
230}
231
232struct image *filter_trick(struct image *img)
233{
234#define TSIZE 3
235    struct image *dst;
236    int x, y, i, j, val, m, more, l, less;
237    int r, g, b;
238
239    dst = image_new(img->width, img->height);
240
241    for(y = 0; y < img->height; y++)
242        for(x = 0; x < img->width; x++)
243            setpixel(dst, x, y, 255, 255, 255);
244
245    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
246        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
247        {
248            getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
249            m = more = l = less = 0;
250            for(i = 0; i < TSIZE; i++)
251                for(j = 0; j < TSIZE; j++)
252                {
253                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
254                    if(r > val)
255                    {
256                        more += r;
257                        m++;
258                    }
259                    else if(r < val)
260                    {
261                        less += r;
262                        l++;
263                    }
264                }
265
266            if(l >= 6)
267                i = less / l;
268            else if(m >= 6)
269                i = more / m;
270            else
271                i = val;
272            setpixel(dst, x, y, i, i, i);
273        }
274
275    return dst;
276}
277
278struct image *filter_smooth(struct image *img)
279{
280#define SSIZE 3
281    struct image *dst;
282    int x, y, i, j, val;
283    int r, g, b;
284
285    dst = image_new(img->width, img->height);
286
287    for(y = 0; y < img->height; y++)
288        for(x = 0; x < img->width; x++)
289            setpixel(dst, x, y, 255, 255, 255);
290
291    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
292        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
293        {
294            val = 0;
295            for(i = 0; i < SSIZE; i++)
296                for(j = 0; j < SSIZE; j++)
297                {
298                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
299                    val += r;
300                }
301
302            i = val / (SSIZE * SSIZE);
303            setpixel(dst, x, y, i, i, i);
304        }
305
306    return dst;
307}
308
309struct image *filter_median(struct image *img)
310{
311#define MSIZE 3
312    struct image *dst;
313    int x, y, i, j, val[MSIZE*MSIZE];
314    int r, g, b;
315
316    dst = image_new(img->width, img->height);
317
318    for(y = 0; y < img->height; y++)
319        for(x = 0; x < img->width; x++)
320            setpixel(dst, x, y, 255, 255, 255);
321
322    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
323        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
324        {
325            for(i = 0; i < MSIZE; i++)
326                for(j = 0; j < MSIZE; j++)
327                {
328                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
329                    val[i * MSIZE + j] = r;
330                }
331
332            /* Bubble sort power! */
333            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
334                for(j = i + 1; j < MSIZE * MSIZE; j++)
335                    if(val[i] > val[j])
336                    {
337                        register int k = val[i];
338                        val[i] = val[j];
339                        val[j] = k;
340                    }
341
342            i = val[MSIZE * MSIZE / 2];
343            setpixel(dst, x, y, i, i, i);
344        }
345
346    return dst;
347}
348
349struct image *filter_contrast(struct image *img)
350{
351    struct image *dst;
352    int histo[256];
353    int x, y, i, min = 255, max = 0;
354    int r, g, b;
355
356    dst = image_new(img->width, img->height);
357
358    for(y = 0; y < img->height; y++)
359        for(x = 0; x < img->width; x++)
360        {
361            getgray(img, x, y, &r);
362            if(r < min) min = r;
363            if(r > max) max = r;
364        }
365
366    if(min == max)
367        histo[min] = 127;
368    else
369        for(i = min; i < max; i++)
370            histo[i] = (i - min) * 255 / (max - min);
371
372    for(y = 0; y < img->height; y++)
373        for(x = 0; x < img->width; x++)
374        {
375            getgray(img, x, y, &r);
376            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
377        }
378
379    return dst;
380}
381
382struct image *filter_crop(struct image *img,
383                          int xmin, int ymin, int xmax, int ymax)
384{
385    struct image *dst;
386    int x, y;
387    int r, g, b;
388
389    if(xmin < 0)
390        xmin = 0;
391    if(ymin < 0)
392        ymin = 0;
393    if(xmax >= img->width)
394        xmax = img->width - 1;
395    if(ymax >= img->height)
396        ymax = img->height - 1;
397
398    if(xmin >= xmax || ymin >= ymax)
399        return NULL;
400
401    dst = image_new(xmax - xmin, ymax - ymin);
402
403    for(y = 0; y < dst->height; y++)
404        for(x = 0; x < dst->width; x++)
405        {
406            getpixel(img, xmin + x, ymin + y, &r, &g, &b);
407            setpixel(dst, x, y, r, g, b);
408        }
409
410    return dst;
411}
412
413int filter_count(struct image *img)
414{
415    int histo[256];
416    int x, y, i, count = 0;
417    int r, g, b;
418
419    for(i = 0; i < 256; i++)
420        histo[i] = 0;
421
422    for(y = 0; y < img->height; y++)
423        for(x = 0; x < img->width; x++)
424        {
425            getgray(img, x, y, &r);
426            histo[r] = 1;
427        }
428
429    for(i = 0; i < 256; i++)
430        count += histo[i];
431
432    return count;
433}
434
Note: See TracBrowser for help on using the repository browser.