source: pwntcha/trunk/src/filter.c @ 452

Last change on this file since 452 was 452, checked in by Sam Hocevar, 16 years ago
  • also blur borders in filter_blur().
  • Property svn:keywords set to Id
File size: 11.9 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filter.c 452 2005-01-12 02:00:33Z 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/* Functions */
21void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b)
22{
23    int oldr, oldg, oldb;
24    int nextr, nextg, nextb;
25
26    if(x < 0 || y < 0 || x >= img->width || y >= img->height)
27        return;
28
29    getpixel(img, x, y, &oldr, &oldg, &oldb);
30    setpixel(img, x, y, r, g, b);
31
32    getpixel(img, x + 1, y, &nextr, &nextg, &nextb);
33    if(nextr == oldr && nextg == oldg && nextb == oldb)
34        filter_flood_fill(img, x + 1, y, r, g, b);
35
36    getpixel(img, x - 1, y, &nextr, &nextg, &nextb);
37    if(nextr == oldr && nextg == oldg && nextb == oldb)
38        filter_flood_fill(img, x - 1, y, r, g, b);
39
40    getpixel(img, x, y + 1, &nextr, &nextg, &nextb);
41    if(nextr == oldr && nextg == oldg && nextb == oldb)
42        filter_flood_fill(img, x, y + 1, r, g, b);
43
44    getpixel(img, x, y - 1, &nextr, &nextg, &nextb);
45    if(nextr == oldr && nextg == oldg && nextb == oldb)
46        filter_flood_fill(img, x, y - 1, r, g, b);
47}
48
49void filter_scale(struct image *img, float ratio)
50{
51    struct image *dst;
52    int w, h, x, y;
53    int r, g, b;
54
55    w = ratio * img->width;
56    h = ratio * img->height;
57
58    dst = image_new(w, h);
59
60    for(y = 0; y < h; y++)
61        for(x = 0; x < w; x++)
62        {
63            getpixel(img, x / ratio, y / ratio, &r, &g, &b);
64            setpixel(dst, x, y, r, g, b);
65        }
66
67    image_swap(img, dst);
68    image_free(dst);
69}
70
71void filter_fill_holes(struct image *img)
72{
73    struct image *dst;
74    int x, y;
75    int r, g, b;
76
77    dst = image_new(img->width, img->height);
78
79    for(y = 0; y < img->height; y++)
80        for(x = 0; x < img->width; x++)
81        {
82            getpixel(img, x, y, &r, &g, &b);
83            setpixel(dst, x, y, r, g, b);
84        }
85
86    for(y = 0; y < dst->height; y++)
87        for(x = 2; x < dst->width - 2; x++)
88        {
89            int c1, c2, c3, c4, c5;
90            getpixel(img, x-2, y, &c1, &g, &b);
91            getpixel(img, x-1, y, &c2, &g, &b);
92            getpixel(img, x, y, &c3, &g, &b);
93            getpixel(img, x+1, y, &c4, &g, &b);
94            getpixel(img, x+2, y, &c5, &g, &b);
95            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
96                c3 = (c1 + c2 + c4) / 3;
97            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
98                c3 = (c2 + c4 + c5) / 3;
99            setpixel(dst, x, y, c3, c3, c3);
100        }
101
102    for(x = 0; x < dst->width; x++)
103        for(y = 2; y < dst->height - 2; y++)
104        {
105            int c1, c2, c3, c4, c5;
106            getpixel(img, x, y-2, &c1, &g, &b);
107            getpixel(img, x, y-1, &c2, &g, &b);
108            getpixel(img, x, y, &c3, &g, &b);
109            getpixel(img, x, y+1, &c4, &g, &b);
110            getpixel(img, x, y+2, &c5, &g, &b);
111            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
112                c3 = (c1 + c2 + c4) / 3;
113            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
114                c3 = (c2 + c4 + c5) / 3;
115            setpixel(dst, x, y, c3, c3, c3);
116        }
117
118    image_swap(img, dst);
119    image_free(dst);
120}
121
122void filter_black_stuff(struct image *img)
123{
124    struct image *dst;
125    int x, y;
126    int r, ra, rb, g, b;
127
128    dst = image_new(img->width, img->height);
129
130    /* Remove vertical stuff */
131    for(y = 0; y < img->height; y++)
132        for(x = 0; x < img->width; x++)
133        {
134            getpixel(img, x, y, &r, &g, &b);
135            setpixel(dst, x, y, r, g, b);
136            if(y > 0 && y < img->height - 1)
137            {
138                getpixel(img, x, y - 1, &ra, &g, &b);
139                getpixel(img, x, y + 1, &rb, &g, &b);
140                if(r < ra && (r - ra) * (r - rb) > 5000)
141                    setpixel(dst, x, y, ra, ra, ra);
142            }
143        }
144
145    /* Remove horizontal stuff */
146    for(y = 0; y < img->height; y++)
147        for(x = 0; x < img->width; x++)
148        {
149            getpixel(img, x, y, &r, &g, &b);
150            if(x > 0 && x < img->width - 1)
151            {
152                getpixel(dst, x - 1, y, &ra, &g, &b);
153                getpixel(dst, x + 1, y, &rb, &g, &b);
154                if(r < ra && (r - ra) * (r - rb) > 5000)
155                    setpixel(dst, x, y, ra, ra, ra);
156            }
157        }
158
159    image_swap(img, dst);
160    image_free(dst);
161}
162
163void 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    image_swap(img, dst);
201    image_free(dst);
202}
203
204void filter_equalize(struct image *img, int threshold)
205{
206    struct image *dst;
207    int x, y;
208    int r, g, b;
209    int min = 0, max = 255;
210
211    dst = image_new(img->width, img->height);
212
213    if(threshold < 0)
214    {
215        min = 255;
216        max = 0;
217        threshold = -threshold;
218    }
219
220    threshold *= 3;
221
222    for(y = 0; y < img->height; y++)
223        for(x = 0; x < img->width; x++)
224        {
225            getpixel(img, x, y, &r, &g, &b);
226            if(r + g + b < threshold)
227                setpixel(dst, x, y, min, min, min);
228            else
229                setpixel(dst, x, y, max, max, max);
230        }
231
232    image_swap(img, dst);
233    image_free(dst);
234}
235
236void filter_trick(struct image *img)
237{
238#define TSIZE 3
239    struct image *dst;
240    int x, y, i, j, val, m, more, l, less;
241    int r, g, b;
242
243    dst = image_new(img->width, img->height);
244
245    for(y = 0; y < img->height; y++)
246        for(x = 0; x < img->width; x++)
247            setpixel(dst, x, y, 255, 255, 255);
248
249    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
250        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
251        {
252            getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
253            m = more = l = less = 0;
254            for(i = 0; i < TSIZE; i++)
255                for(j = 0; j < TSIZE; j++)
256                {
257                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
258                    if(r > val)
259                    {
260                        more += r;
261                        m++;
262                    }
263                    else if(r < val)
264                    {
265                        less += r;
266                        l++;
267                    }
268                }
269
270            if(l >= 6)
271                i = less / l;
272            else if(m >= 6)
273                i = more / m;
274            else
275                i = val;
276            setpixel(dst, x, y, i, i, i);
277        }
278
279    image_swap(img, dst);
280    image_free(dst);
281}
282
283void filter_smooth(struct image *img)
284{
285#define SSIZE 3
286    struct image *dst;
287    int x, y, i, j, val;
288    int r, g, b;
289
290    dst = image_new(img->width, img->height);
291
292    for(y = 0; y < img->height; y++)
293        for(x = 0; x < img->width; x++)
294        {
295            getpixel(img, x, y, &r, &g, &b);
296            setpixel(dst, x, y, r, g, b);
297        }
298
299    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
300        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
301        {
302            val = 0;
303            for(i = 0; i < SSIZE; i++)
304                for(j = 0; j < SSIZE; j++)
305                {
306                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
307                    val += r;
308                }
309
310            i = val / (SSIZE * SSIZE);
311            setpixel(dst, x, y, i, i, i);
312        }
313
314    /* Remove border */
315    for(y = 0; y < dst->height; y++)
316    {
317        getpixel(dst, 1, y, &r, &g, &b);
318        setpixel(dst, 0, y, r, g, b);
319        getpixel(dst, dst->width - 2, y, &r, &g, &b);
320        setpixel(dst, dst->width - 1, y, r, g, b);
321    }
322
323    for(x = 0; x < dst->width; x++)
324    {
325        getpixel(dst, x, 1, &r, &g, &b);
326        setpixel(dst, x, 0, r, g, b);
327        getpixel(dst, x, dst->height - 2, &r, &g, &b);
328        setpixel(dst, x, dst->height - 1, r, g, b);
329    }
330
331    image_swap(img, dst);
332    image_free(dst);
333}
334
335void filter_median(struct image *img)
336{
337#define MSIZE 3
338    struct image *dst;
339    int x, y, i, j, val[MSIZE*MSIZE];
340    int r, g, b;
341
342    dst = image_new(img->width, img->height);
343
344    for(y = 0; y < img->height; y++)
345        for(x = 0; x < img->width; x++)
346            setpixel(dst, x, y, 255, 255, 255);
347
348    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
349        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
350        {
351            for(i = 0; i < MSIZE; i++)
352                for(j = 0; j < MSIZE; j++)
353                {
354                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
355                    val[i * MSIZE + j] = r;
356                }
357
358            /* Bubble sort power! */
359            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
360                for(j = i + 1; j < MSIZE * MSIZE; j++)
361                    if(val[i] > val[j])
362                    {
363                        register int k = val[i];
364                        val[i] = val[j];
365                        val[j] = k;
366                    }
367
368            i = val[MSIZE * MSIZE / 2];
369            setpixel(dst, x, y, i, i, i);
370        }
371
372    image_swap(img, dst);
373    image_free(dst);
374}
375
376void filter_contrast(struct image *img)
377{
378    struct image *dst;
379    int histo[256];
380    int x, y, i, min = 255, max = 0;
381    int r, g, b;
382
383    dst = image_new(img->width, img->height);
384
385    for(y = 0; y < img->height; y++)
386        for(x = 0; x < img->width; x++)
387        {
388            getgray(img, x, y, &r);
389            if(r < min) min = r;
390            if(r > max) max = r;
391        }
392
393    if(min == max)
394        histo[min] = 127;
395    else
396        for(i = min; i < max + 1; i++)
397            histo[i] = (i - min) * 255 / (max - min);
398
399    for(y = 0; y < img->height; y++)
400        for(x = 0; x < img->width; x++)
401        {
402            getgray(img, x, y, &r);
403            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
404        }
405
406    image_swap(img, dst);
407    image_free(dst);
408}
409
410void filter_crop(struct image *img, int xmin, int ymin, int xmax, int ymax)
411{
412    struct image *dst;
413    int x, y;
414    int r, g, b;
415
416    if(xmin < 0)
417        xmin = 0;
418    if(ymin < 0)
419        ymin = 0;
420    if(xmax >= img->width)
421        xmax = img->width - 1;
422    if(ymax >= img->height)
423        ymax = img->height - 1;
424
425    if(xmin >= xmax || ymin >= ymax)
426        return;
427
428    dst = image_new(xmax - xmin, ymax - ymin);
429
430    for(y = 0; y < dst->height; y++)
431        for(x = 0; x < dst->width; x++)
432        {
433            getpixel(img, xmin + x, ymin + y, &r, &g, &b);
434            setpixel(dst, x, y, r, g, b);
435        }
436
437    image_swap(img, dst);
438    image_free(dst);
439}
440
441int filter_count(struct image *img)
442{
443    int histo[256];
444    int x, y, i, count = 0;
445    int r, g, b;
446
447    for(i = 0; i < 256; i++)
448        histo[i] = 0;
449
450    for(y = 0; y < img->height; y++)
451        for(x = 0; x < img->width; x++)
452        {
453            getgray(img, x, y, &r);
454            histo[r] = 1;
455        }
456
457    for(i = 0; i < 256; i++)
458        count += histo[i];
459
460    return count;
461}
462
Note: See TracBrowser for help on using the repository browser.