source: toilet/trunk/src/filter.c @ 1228

Last change on this file since 1228 was 1228, checked in by Sam Hocevar, 13 years ago
  • Added filter_flip, filter_flop and filter_rotate.
  • Add a -F flag to specify filters to apply. Can be specified more than once, and filters can be chained using ":", eg. "-F flip:gay".
  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1/*
2 *  TOIlet        The Other Implementation’s letters
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: filter.c 1228 2006-10-25 16:06:19Z sam $
7 *
8 *  This program is free software; you can redistribute it and/or
9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
12 */
13
14/*
15 * This file contains post-processing filter functions.
16 */
17
18#include "config.h"
19
20#if defined(HAVE_INTTYPES_H)
21#   include <inttypes.h>
22#endif
23#include <string.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <cucul.h>
27
28#include "toilet.h"
29#include "filter.h"
30
31static void filter_crop(cucul_canvas_t *);
32static void filter_gay(cucul_canvas_t *);
33static void filter_metal(cucul_canvas_t *);
34static void filter_flip(cucul_canvas_t *);
35static void filter_flop(cucul_canvas_t *);
36static void filter_rotate(cucul_canvas_t *);
37
38struct
39{
40    char const *name;
41    void (*function)(cucul_canvas_t *);
42}
43const lookup[] =
44{
45    { "crop", filter_crop },
46    { "gay", filter_gay },
47    { "metal", filter_metal },
48    { "flip", filter_flip },
49    { "flop", filter_flop },
50    { "rotate", filter_rotate },
51};
52
53int filter_add(context_t *cx, char const *filter)
54{
55    unsigned int n;
56    int i;
57
58    for(;;)
59    {
60        while(*filter == ':')
61            filter++;
62
63        if(*filter == '\0')
64            break;
65
66        for(i = sizeof(lookup) / sizeof(lookup[0]); i--; )
67            if(!strncmp(filter, lookup[i].name, strlen(lookup[i].name)))
68                break;
69
70        n = strlen(lookup[i].name);
71
72        if(i == -1 || (filter[n] != ':' && filter[n] != '\0'))
73        {
74            fprintf(stderr, "unknown filter near `%s'\n", filter);
75            return -1;
76        }
77
78        if((cx->nfilters % 16) == 0)
79            cx->filters = realloc(cx->filters, (cx->nfilters + 16)
80                                                 * sizeof(lookup[0].function));
81        cx->filters[cx->nfilters] = lookup[i].function;
82        cx->nfilters++;
83
84        filter += n;
85    }
86
87    return 0;
88}
89
90int filter_do(context_t *cx)
91{
92    unsigned int i;
93
94    for(i = 0; i < cx->nfilters; i++)
95        cx->filters[i](cx->cv);
96
97    return 0;
98}
99
100static void filter_crop(cucul_canvas_t *cv)
101{
102    unsigned int x, y, w, h;
103    unsigned int xmin, xmax, ymin, ymax;
104
105    xmin = w = cucul_get_canvas_width(cv);
106    xmax = 0;
107    ymin = h = cucul_get_canvas_height(cv);
108    ymax = 0;
109
110    for(y = 0; y < h; y++)
111        for(x = 0; x < w; x++)
112    {
113        unsigned long int ch = cucul_getchar(cv, x, y);
114        if(ch != (unsigned char)' ')
115        {
116            if(x < xmin)
117                xmin = x;
118            if(x > xmax)
119                xmax = x;
120            if(y < ymin)
121                ymin = y;
122            if(y > ymax)
123                ymax = y;
124        }
125    }
126
127    if(xmax < xmin || ymax < ymin)
128        return;
129
130    cucul_set_canvas_boundaries(cv, xmin, ymin,
131                                xmax - xmin + 1, ymax - ymin + 1);
132}
133
134static void filter_metal(cucul_canvas_t *cv)
135{
136    static unsigned char const palette[] =
137    {
138        CUCUL_COLOR_LIGHTBLUE,
139        CUCUL_COLOR_BLUE,
140        CUCUL_COLOR_LIGHTGRAY,
141        CUCUL_COLOR_DARKGRAY,
142    };
143
144    unsigned int x, y, w, h;
145
146    w = cucul_get_canvas_width(cv);
147    h = cucul_get_canvas_height(cv);
148
149    for(y = 0; y < h; y++)
150        for(x = 0; x < w; x++)
151    {
152        unsigned long int ch = cucul_getchar(cv, x, y);
153        int i;
154
155        if(ch == (unsigned char)' ')
156            continue;
157
158        i = y * 4 / h;
159        cucul_set_color(cv, palette[i], CUCUL_COLOR_TRANSPARENT);
160        cucul_putchar(cv, x, y, ch);
161    }
162}
163
164static void filter_gay(cucul_canvas_t *cv)
165{
166    static unsigned char const rainbow[] =
167    {
168        CUCUL_COLOR_LIGHTMAGENTA,
169        CUCUL_COLOR_LIGHTRED,
170        CUCUL_COLOR_YELLOW,
171        CUCUL_COLOR_LIGHTGREEN,
172        CUCUL_COLOR_LIGHTCYAN,
173        CUCUL_COLOR_LIGHTBLUE,
174    };
175    unsigned int x, y, w, h;
176
177    w = cucul_get_canvas_width(cv);
178    h = cucul_get_canvas_height(cv);
179
180    for(y = 0; y < h; y++)
181        for(x = 0; x < w; x++)
182    {
183        unsigned long int ch = cucul_getchar(cv, x, y);
184        if(ch != (unsigned char)' ')
185        {
186            cucul_set_color(cv, rainbow[(x / 2 + y) % 6],
187                                CUCUL_COLOR_TRANSPARENT);
188            cucul_putchar(cv, x, y, ch);
189        }
190    }
191}
192
193static void filter_flip(cucul_canvas_t *cv)
194{
195    cucul_flip(cv);
196}
197
198static void filter_flop(cucul_canvas_t *cv)
199{
200    cucul_flop(cv);
201}
202
203static void filter_rotate(cucul_canvas_t *cv)
204{
205    cucul_rotate(cv);
206}
207
Note: See TracBrowser for help on using the repository browser.