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

Last change on this file since 448 was 448, checked in by Sam Hocevar, 16 years ago
  • Use font_load_* for all decoders.
  • Property svn:keywords set to Id
File size: 11.4 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filter.c 448 2005-01-10 15:31: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            setpixel(dst, x, y, 255, 255, 255);
295
296    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
297        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
298        {
299            val = 0;
300            for(i = 0; i < SSIZE; i++)
301                for(j = 0; j < SSIZE; j++)
302                {
303                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
304                    val += r;
305                }
306
307            i = val / (SSIZE * SSIZE);
308            setpixel(dst, x, y, i, i, i);
309        }
310
311    image_swap(img, dst);
312    image_free(dst);
313}
314
315void filter_median(struct image *img)
316{
317#define MSIZE 3
318    struct image *dst;
319    int x, y, i, j, val[MSIZE*MSIZE];
320    int r, g, b;
321
322    dst = image_new(img->width, img->height);
323
324    for(y = 0; y < img->height; y++)
325        for(x = 0; x < img->width; x++)
326            setpixel(dst, x, y, 255, 255, 255);
327
328    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
329        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
330        {
331            for(i = 0; i < MSIZE; i++)
332                for(j = 0; j < MSIZE; j++)
333                {
334                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
335                    val[i * MSIZE + j] = r;
336                }
337
338            /* Bubble sort power! */
339            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
340                for(j = i + 1; j < MSIZE * MSIZE; j++)
341                    if(val[i] > val[j])
342                    {
343                        register int k = val[i];
344                        val[i] = val[j];
345                        val[j] = k;
346                    }
347
348            i = val[MSIZE * MSIZE / 2];
349            setpixel(dst, x, y, i, i, i);
350        }
351
352    image_swap(img, dst);
353    image_free(dst);
354}
355
356void filter_contrast(struct image *img)
357{
358    struct image *dst;
359    int histo[256];
360    int x, y, i, min = 255, max = 0;
361    int r, g, b;
362
363    dst = image_new(img->width, img->height);
364
365    for(y = 0; y < img->height; y++)
366        for(x = 0; x < img->width; x++)
367        {
368            getgray(img, x, y, &r);
369            if(r < min) min = r;
370            if(r > max) max = r;
371        }
372
373    if(min == max)
374        histo[min] = 127;
375    else
376        for(i = min; i < max + 1; i++)
377            histo[i] = (i - min) * 255 / (max - min);
378
379    for(y = 0; y < img->height; y++)
380        for(x = 0; x < img->width; x++)
381        {
382            getgray(img, x, y, &r);
383            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
384        }
385
386    image_swap(img, dst);
387    image_free(dst);
388}
389
390void filter_crop(struct image *img, int xmin, int ymin, int xmax, int ymax)
391{
392    struct image *dst;
393    int x, y;
394    int r, g, b;
395
396    if(xmin < 0)
397        xmin = 0;
398    if(ymin < 0)
399        ymin = 0;
400    if(xmax >= img->width)
401        xmax = img->width - 1;
402    if(ymax >= img->height)
403        ymax = img->height - 1;
404
405    if(xmin >= xmax || ymin >= ymax)
406        return;
407
408    dst = image_new(xmax - xmin, ymax - ymin);
409
410    for(y = 0; y < dst->height; y++)
411        for(x = 0; x < dst->width; x++)
412        {
413            getpixel(img, xmin + x, ymin + y, &r, &g, &b);
414            setpixel(dst, x, y, r, g, b);
415        }
416
417    image_swap(img, dst);
418    image_free(dst);
419}
420
421int filter_count(struct image *img)
422{
423    int histo[256];
424    int x, y, i, count = 0;
425    int r, g, b;
426
427    for(i = 0; i < 256; i++)
428        histo[i] = 0;
429
430    for(y = 0; y < img->height; y++)
431        for(x = 0; x < img->width; x++)
432        {
433            getgray(img, x, y, &r);
434            histo[r] = 1;
435        }
436
437    for(i = 0; i < 256; i++)
438        count += histo[i];
439
440    return count;
441}
442
Note: See TracBrowser for help on using the repository browser.