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

Last change on this file since 4400 was 2315, checked in by Sam Hocevar, 14 years ago
  • Update build system and licensing terms to 2008 standards.
  • Property svn:keywords set to Id
File size: 12.0 KB
Line 
1/*
2 * filters.c: various image filters
3 * $Id: filter.c 2315 2008-04-26 07:25:03Z sam $
4 *
5 * Copyright: (c) 2004 Sam Hocevar <sam@zoy.org>
6 *  This program is free software. It comes without any warranty, to
7 *  the extent permitted by applicable law. You can redistribute it
8 *  and/or modify it under the terms of the Do What The Fuck You Want
9 *  To Public License, Version 2, as published by Sam Hocevar. See
10 *  http://sam.zoy.org/wtfpl/COPYING for more details.
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <math.h>
17
18#include "config.h"
19#include "common.h"
20
21/* Functions */
22void filter_flood_fill(struct image *img, int x, int y, int r, int g, int b)
23{
24    int oldr, oldg, oldb;
25    int nextr, nextg, nextb;
26
27    if(x < 0 || y < 0 || x >= img->width || y >= img->height)
28        return;
29
30    getpixel(img, x, y, &oldr, &oldg, &oldb);
31    setpixel(img, x, y, r, g, b);
32
33    getpixel(img, x + 1, y, &nextr, &nextg, &nextb);
34    if(nextr == oldr && nextg == oldg && nextb == oldb)
35        filter_flood_fill(img, x + 1, y, r, g, b);
36
37    getpixel(img, x - 1, y, &nextr, &nextg, &nextb);
38    if(nextr == oldr && nextg == oldg && nextb == oldb)
39        filter_flood_fill(img, x - 1, y, r, g, b);
40
41    getpixel(img, x, y + 1, &nextr, &nextg, &nextb);
42    if(nextr == oldr && nextg == oldg && nextb == oldb)
43        filter_flood_fill(img, x, y + 1, r, g, b);
44
45    getpixel(img, x, y - 1, &nextr, &nextg, &nextb);
46    if(nextr == oldr && nextg == oldg && nextb == oldb)
47        filter_flood_fill(img, x, y - 1, r, g, b);
48}
49
50void filter_scale(struct image *img, float ratio)
51{
52    struct image *dst;
53    int w, h, x, y;
54    int r, g, b;
55
56    w = ratio * img->width;
57    h = ratio * img->height;
58
59    dst = image_new(w, h);
60
61    for(y = 0; y < h; y++)
62        for(x = 0; x < w; x++)
63        {
64            getpixel(img, x / ratio, y / ratio, &r, &g, &b);
65            setpixel(dst, x, y, r, g, b);
66        }
67
68    image_swap(img, dst);
69    image_free(dst);
70}
71
72void filter_fill_holes(struct image *img)
73{
74    struct image *dst;
75    int x, y;
76    int r, g, b;
77
78    dst = image_new(img->width, img->height);
79
80    for(y = 0; y < img->height; y++)
81        for(x = 0; x < img->width; x++)
82        {
83            getpixel(img, x, y, &r, &g, &b);
84            setpixel(dst, x, y, r, g, b);
85        }
86
87    for(y = 0; y < dst->height; y++)
88        for(x = 2; x < dst->width - 2; x++)
89        {
90            int c1, c2, c3, c4, c5;
91            getpixel(img, x-2, y, &c1, &g, &b);
92            getpixel(img, x-1, y, &c2, &g, &b);
93            getpixel(img, x, y, &c3, &g, &b);
94            getpixel(img, x+1, y, &c4, &g, &b);
95            getpixel(img, x+2, y, &c5, &g, &b);
96            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
97                c3 = (c1 + c2 + c4) / 3;
98            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
99                c3 = (c2 + c4 + c5) / 3;
100            setpixel(dst, x, y, c3, c3, c3);
101        }
102
103    for(x = 0; x < dst->width; x++)
104        for(y = 2; y < dst->height - 2; y++)
105        {
106            int c1, c2, c3, c4, c5;
107            getpixel(img, x, y-2, &c1, &g, &b);
108            getpixel(img, x, y-1, &c2, &g, &b);
109            getpixel(img, x, y, &c3, &g, &b);
110            getpixel(img, x, y+1, &c4, &g, &b);
111            getpixel(img, x, y+2, &c5, &g, &b);
112            if(c1 < 127 && c2 < 127 && c3 > 128 && c4 < 127)
113                c3 = (c1 + c2 + c4) / 3;
114            else if(c2 < 127 && c3 > 128 && c4 < 127 && c5 < 127)
115                c3 = (c2 + c4 + c5) / 3;
116            setpixel(dst, x, y, c3, c3, c3);
117        }
118
119    image_swap(img, dst);
120    image_free(dst);
121}
122
123void 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    image_swap(img, dst);
161    image_free(dst);
162}
163
164void filter_detect_lines(struct image *img)
165{
166    struct image *dst;
167    int x, y;
168    int r, ra, rb, g, b;
169
170    dst = image_new(img->width, img->height);
171
172    /* Remove white lines */
173    for(y = 0; y < img->height; y++)
174        for(x = 0; x < img->width; x++)
175        {
176            getpixel(img, x, y, &r, &g, &b);
177            setpixel(dst, x, y, r, g, b);
178            if(y > 0 && y < img->height - 1)
179            {
180                getpixel(img, x, y - 1, &ra, &g, &b);
181                getpixel(img, x, y + 1, &rb, &g, &b);
182                if(r > ra && (r - ra) * (r - rb) > 5000)
183                    setpixel(dst, x, y, ra, ra, ra);
184            }
185        }
186
187    /* Remove black lines */
188    for(y = 0; y < img->height; y++)
189        for(x = 0; x < img->width; x++)
190        {
191            getpixel(dst, x, y, &r, &g, &b);
192            if(y > 0 && y < img->height - 1)
193            {
194                getpixel(img, x, y - 1, &ra, &g, &b);
195                getpixel(img, x, y + 1, &rb, &g, &b);
196                if(r < ra && (r - ra) * (r - rb) > 500)
197                    setpixel(dst, x, y, ra, ra, ra);
198            }
199        }
200
201    image_swap(img, dst);
202    image_free(dst);
203}
204
205void filter_threshold(struct image *img, int threshold)
206{
207    struct image *dst;
208    int x, y;
209    int r, g, b;
210    int min = 0, max = 255;
211
212    dst = image_new(img->width, img->height);
213
214    if(threshold < 0)
215    {
216        min = 255;
217        max = 0;
218        threshold = -threshold;
219    }
220
221    threshold *= 3;
222
223    for(y = 0; y < img->height; y++)
224        for(x = 0; x < img->width; x++)
225        {
226            getpixel(img, x, y, &r, &g, &b);
227            if(r + g + b < threshold)
228                setpixel(dst, x, y, min, min, min);
229            else
230                setpixel(dst, x, y, max, max, max);
231        }
232
233    image_swap(img, dst);
234    image_free(dst);
235}
236
237void filter_trick(struct image *img)
238{
239#define TSIZE 3
240    struct image *dst;
241    int x, y, i, j, val, m, more, l, less;
242    int r, g, b;
243
244    dst = image_new(img->width, img->height);
245
246    for(y = 0; y < img->height; y++)
247        for(x = 0; x < img->width; x++)
248            setpixel(dst, x, y, 255, 255, 255);
249
250    for(y = TSIZE/2; y < img->height - TSIZE/2; y++)
251        for(x = TSIZE/2; x < img->width - TSIZE/2; x++)
252        {
253            getpixel(img, x + TSIZE - TSIZE/2, y + TSIZE - TSIZE/2, &val, &g, &b);
254            m = more = l = less = 0;
255            for(i = 0; i < TSIZE; i++)
256                for(j = 0; j < TSIZE; j++)
257                {
258                    getpixel(img, x + j - TSIZE/2, y + i - TSIZE/2, &r, &g, &b);
259                    if(r > val)
260                    {
261                        more += r;
262                        m++;
263                    }
264                    else if(r < val)
265                    {
266                        less += r;
267                        l++;
268                    }
269                }
270
271            if(l >= 6)
272                i = less / l;
273            else if(m >= 6)
274                i = more / m;
275            else
276                i = val;
277            setpixel(dst, x, y, i, i, i);
278        }
279
280    image_swap(img, dst);
281    image_free(dst);
282}
283
284void filter_smooth(struct image *img)
285{
286#define SSIZE 3
287    struct image *dst;
288    int x, y, i, j, val;
289    int r, g, b;
290
291    dst = image_new(img->width, img->height);
292
293    for(y = 0; y < img->height; y++)
294        for(x = 0; x < img->width; x++)
295        {
296            getpixel(img, x, y, &r, &g, &b);
297            setpixel(dst, x, y, r, g, b);
298        }
299
300    for(y = SSIZE/2; y < img->height - SSIZE/2; y++)
301        for(x = SSIZE/2; x < img->width - SSIZE/2; x++)
302        {
303            val = 0;
304            for(i = 0; i < SSIZE; i++)
305                for(j = 0; j < SSIZE; j++)
306                {
307                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
308                    val += r;
309                }
310
311            i = val / (SSIZE * SSIZE);
312            setpixel(dst, x, y, i, i, i);
313        }
314
315    /* Remove border */
316    for(y = 0; y < dst->height; y++)
317    {
318        getpixel(dst, 1, y, &r, &g, &b);
319        setpixel(dst, 0, y, r, g, b);
320        getpixel(dst, dst->width - 2, y, &r, &g, &b);
321        setpixel(dst, dst->width - 1, y, r, g, b);
322    }
323
324    for(x = 0; x < dst->width; x++)
325    {
326        getpixel(dst, x, 1, &r, &g, &b);
327        setpixel(dst, x, 0, r, g, b);
328        getpixel(dst, x, dst->height - 2, &r, &g, &b);
329        setpixel(dst, x, dst->height - 1, r, g, b);
330    }
331
332    image_swap(img, dst);
333    image_free(dst);
334}
335
336void filter_median(struct image *img)
337{
338#define MSIZE 3
339    struct image *dst;
340    int x, y, i, j, val[MSIZE*MSIZE];
341    int r, g, b;
342
343    dst = image_new(img->width, img->height);
344
345    for(y = 0; y < img->height; y++)
346        for(x = 0; x < img->width; x++)
347            setpixel(dst, x, y, 255, 255, 255);
348
349    for(y = MSIZE/2; y < img->height - MSIZE/2; y++)
350        for(x = MSIZE/2; x < img->width - MSIZE/2; x++)
351        {
352            for(i = 0; i < MSIZE; i++)
353                for(j = 0; j < MSIZE; j++)
354                {
355                    getpixel(img, x + j - SSIZE/2, y + i - SSIZE/2, &r, &g, &b);
356                    val[i * MSIZE + j] = r;
357                }
358
359            /* Bubble sort power! */
360            for(i = 0; i < MSIZE * MSIZE / 2 + 1; i++)
361                for(j = i + 1; j < MSIZE * MSIZE; j++)
362                    if(val[i] > val[j])
363                    {
364                        register int k = val[i];
365                        val[i] = val[j];
366                        val[j] = k;
367                    }
368
369            i = val[MSIZE * MSIZE / 2];
370            setpixel(dst, x, y, i, i, i);
371        }
372
373    image_swap(img, dst);
374    image_free(dst);
375}
376
377void filter_contrast(struct image *img)
378{
379    struct image *dst;
380    int histo[256];
381    int x, y, i, min = 255, max = 0;
382    int r, g, b;
383
384    dst = image_new(img->width, img->height);
385
386    for(y = 0; y < img->height; y++)
387        for(x = 0; x < img->width; x++)
388        {
389            getgray(img, x, y, &r);
390            if(r < min) min = r;
391            if(r > max) max = r;
392        }
393
394    if(min == max)
395        histo[min] = 127;
396    else
397        for(i = min; i < max + 1; i++)
398            histo[i] = (i - min) * 255 / (max - min);
399
400    for(y = 0; y < img->height; y++)
401        for(x = 0; x < img->width; x++)
402        {
403            getgray(img, x, y, &r);
404            setpixel(dst, x, y, histo[r], histo[r], histo[r]);
405        }
406
407    image_swap(img, dst);
408    image_free(dst);
409}
410
411void filter_crop(struct image *img, int xmin, int ymin, int xmax, int ymax)
412{
413    struct image *dst;
414    int x, y;
415    int r, g, b;
416
417    if(xmin < 0)
418        xmin = 0;
419    if(ymin < 0)
420        ymin = 0;
421    if(xmax >= img->width)
422        xmax = img->width - 1;
423    if(ymax >= img->height)
424        ymax = img->height - 1;
425
426    if(xmin >= xmax || ymin >= ymax)
427        return;
428
429    dst = image_new(xmax - xmin, ymax - ymin);
430
431    for(y = 0; y < dst->height; y++)
432        for(x = 0; x < dst->width; x++)
433        {
434            getpixel(img, xmin + x, ymin + y, &r, &g, &b);
435            setpixel(dst, x, y, r, g, b);
436        }
437
438    image_swap(img, dst);
439    image_free(dst);
440}
441
442int filter_count(struct image *img)
443{
444    int histo[256];
445    int x, y, i, count = 0;
446    int r, g, b;
447
448    for(i = 0; i < 256; i++)
449        histo[i] = 0;
450
451    for(y = 0; y < img->height; y++)
452        for(x = 0; x < img->width; x++)
453        {
454            getgray(img, x, y, &r);
455            histo[r] = 1;
456        }
457
458    for(i = 0; i < 256; i++)
459        count += histo[i];
460
461    return count;
462}
463
Note: See TracBrowser for help on using the repository browser.