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

Last change on this file since 417 was 417, checked in by Sam Hocevar, 16 years ago
  • do equalizing on grayscale image.
  • Property svn:keywords set to Id
File size: 11.4 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filters.c 417 2005-01-04 18:43:28Z 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    threshold *= 3;
220
221    for(y = 0; y < img->height; y++)
222        for(x = 0; x < img->width; x++)
223        {
224            getpixel(img, x, y, &r, &g, &b);
225            if(r + g + b < threshold)
226                setpixel(dst, x, y, min, min, min);
227            else
228                setpixel(dst, x, y, max, max, max);
229        }
230
231    return dst;
232}
233
234struct image *filter_trick(struct image *img)
235{
236#define TSIZE 3
237    struct image *dst;
238    int x, y, i, j, val, m, more, l, less;
239    int r, g, b;
240
241    dst = image_new(img->width, img->height);
242
243    for(y = 0; y < img->height; y++)
244        for(x = 0; x < img->width; x++)
245            setpixel(dst, x, y, 255, 255, 255);
246
247    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
248        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
249        {
250            getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
251            m = more = l = less = 0;
252            for(i = 0; i < TSIZE; i++)
253                for(j = 0; j < TSIZE; j++)
254                {
255                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
256                    if(r > val)
257                    {
258                        more += r;
259                        m++;
260                    }
261                    else if(r < val)
262                    {
263                        less += r;
264                        l++;
265                    }
266                }
267
268            if(l >= 6)
269                i = less / l;
270            else if(m >= 6)
271                i = more / m;
272            else
273                i = val;
274            setpixel(dst, x, y, i, i, i);
275        }
276
277    return dst;
278}
279
280struct image *filter_smooth(struct image *img)
281{
282#define SSIZE 3
283    struct image *dst;
284    int x, y, i, j, val;
285    int r, g, b;
286
287    dst = image_new(img->width, img->height);
288
289    for(y = 0; y < img->height; y++)
290        for(x = 0; x < img->width; x++)
291            setpixel(dst, x, y, 255, 255, 255);
292
293    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
294        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
295        {
296            val = 0;
297            for(i = 0; i < SSIZE; i++)
298                for(j = 0; j < SSIZE; j++)
299                {
300                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
301                    val += r;
302                }
303
304            i = val / (SSIZE * SSIZE);
305            setpixel(dst, x, y, i, i, i);
306        }
307
308    return dst;
309}
310
311struct image *filter_median(struct image *img)
312{
313#define MSIZE 3
314    struct image *dst;
315    int x, y, i, j, val[MSIZE*MSIZE];
316    int r, g, b;
317
318    dst = image_new(img->width, img->height);
319
320    for(y = 0; y < img->height; y++)
321        for(x = 0; x < img->width; x++)
322            setpixel(dst, x, y, 255, 255, 255);
323
324    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
325        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
326        {
327            for(i = 0; i < MSIZE; i++)
328                for(j = 0; j < MSIZE; j++)
329                {
330                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
331                    val[i * MSIZE + j] = r;
332                }
333
334            /* Bubble sort power! */
335            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
336                for(j = i + 1; j < MSIZE * MSIZE; j++)
337                    if(val[i] > val[j])
338                    {
339                        register int k = val[i];
340                        val[i] = val[j];
341                        val[j] = k;
342                    }
343
344            i = val[MSIZE * MSIZE / 2];
345            setpixel(dst, x, y, i, i, i);
346        }
347
348    return dst;
349}
350
351struct image *filter_contrast(struct image *img)
352{
353    struct image *dst;
354    int histo[256];
355    int x, y, i, min = 255, max = 0;
356    int r, g, b;
357
358    dst = image_new(img->width, img->height);
359
360    for(y = 0; y < img->height; y++)
361        for(x = 0; x < img->width; x++)
362        {
363            getgray(img, x, y, &r);
364            if(r < min) min = r;
365            if(r > max) max = r;
366        }
367
368    if(min == max)
369        histo[min] = 127;
370    else
371        for(i = min; i < max; i++)
372            histo[i] = (i - min) * 255 / (max - min);
373
374    for(y = 0; y < img->height; y++)
375        for(x = 0; x < img->width; x++)
376        {
377            getgray(img, x, y, &r);
378            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
379        }
380
381    return dst;
382}
383
384struct image *filter_crop(struct image *img,
385                          int xmin, int ymin, int xmax, int ymax)
386{
387    struct image *dst;
388    int x, y;
389    int r, g, b;
390
391    if(xmin < 0)
392        xmin = 0;
393    if(ymin < 0)
394        ymin = 0;
395    if(xmax >= img->width)
396        xmax = img->width - 1;
397    if(ymax >= img->height)
398        ymax = img->height - 1;
399
400    if(xmin >= xmax || ymin >= ymax)
401        return NULL;
402
403    dst = image_new(xmax - xmin, ymax - ymin);
404
405    for(y = 0; y < dst->height; y++)
406        for(x = 0; x < dst->width; x++)
407        {
408            getpixel(img, xmin + x, ymin + y, &r, &g, &b);
409            setpixel(dst, x, y, r, g, b);
410        }
411
412    return dst;
413}
414
415int filter_count(struct image *img)
416{
417    int histo[256];
418    int x, y, i, count = 0;
419    int r, g, b;
420
421    for(i = 0; i < 256; i++)
422        histo[i] = 0;
423
424    for(y = 0; y < img->height; y++)
425        for(x = 0; x < img->width; x++)
426        {
427            getgray(img, x, y, &r);
428            histo[r] = 1;
429        }
430
431    for(i = 0; i < 256; i++)
432        count += histo[i];
433
434    return count;
435}
436
Note: See TracBrowser for help on using the repository browser.