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

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