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

Last change on this file since 1376 was 1376, checked in by Sam Hocevar, 13 years ago
  • Now that libcaca 0.99.beta10 is out, we can switch to the new API.
  • Property svn:keywords set to Id
File size: 5.1 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 1376 2006-11-12 20:37:58Z 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(context_t *);
32static void filter_gay(context_t *);
33static void filter_metal(context_t *);
34static void filter_flip(context_t *);
35static void filter_flop(context_t *);
36static void filter_rotate(context_t *);
37
38struct
39{
40    char const *name;
41    void (*function)(context_t *);
42    char const *description;
43}
44const lookup[] =
45{
46    { "crop", filter_crop, "crop unused blanks" },
47    { "gay", filter_gay, "add a rainbow colour effect" },
48    { "metal", filter_metal, "add a metallic colour effect" },
49    { "flip", filter_flip, "flip horizontally" },
50    { "flop", filter_flop, "flip vertically" },
51    { "rotate", filter_rotate, "perform a 180 degrees rotation" },
52};
53
54int filter_list(void)
55{
56    unsigned int i;
57
58    printf("Available filters:\n");
59    for(i = 0; i < sizeof(lookup) / sizeof(lookup[0]); i++)
60        printf("\"%s\": %s\n", lookup[i].name, lookup[i].description);
61
62    return 0;
63}
64
65int filter_add(context_t *cx, char const *filter)
66{
67    unsigned int n;
68    int i;
69
70    for(;;)
71    {
72        while(*filter == ':')
73            filter++;
74
75        if(*filter == '\0')
76            break;
77
78        for(i = sizeof(lookup) / sizeof(lookup[0]); i--; )
79            if(!strncmp(filter, lookup[i].name, strlen(lookup[i].name)))
80            {
81                n = strlen(lookup[i].name);
82                break;
83            }
84
85        if(i == -1 || (filter[n] != ':' && filter[n] != '\0'))
86        {
87            fprintf(stderr, "unknown filter near `%s'\n", filter);
88            return -1;
89        }
90
91        if((cx->nfilters % 16) == 0)
92            cx->filters = realloc(cx->filters, (cx->nfilters + 16)
93                                                 * sizeof(lookup[0].function));
94        cx->filters[cx->nfilters] = lookup[i].function;
95        cx->nfilters++;
96
97        filter += n;
98    }
99
100    return 0;
101}
102
103int filter_do(context_t *cx)
104{
105    unsigned int i;
106
107    for(i = 0; i < cx->nfilters; i++)
108        cx->filters[i](cx);
109
110    return 0;
111}
112
113int filter_end(context_t *cx)
114{
115    free(cx->filters);
116
117    return 0;
118}
119
120static void filter_crop(context_t *cx)
121{
122    unsigned int x, y, w, h;
123    unsigned int xmin, xmax, ymin, ymax;
124
125    xmin = w = cucul_get_canvas_width(cx->torender);
126    xmax = 0;
127    ymin = h = cucul_get_canvas_height(cx->torender);
128    ymax = 0;
129
130    for(y = 0; y < h; y++)
131        for(x = 0; x < w; x++)
132    {
133        unsigned long int ch = cucul_get_char(cx->torender, x, y);
134        if(ch != (unsigned char)' ')
135        {
136            if(x < xmin)
137                xmin = x;
138            if(x > xmax)
139                xmax = x;
140            if(y < ymin)
141                ymin = y;
142            if(y > ymax)
143                ymax = y;
144        }
145    }
146
147    if(xmax < xmin || ymax < ymin)
148        return;
149
150    cucul_set_canvas_boundaries(cx->torender, xmin, ymin,
151                                xmax - xmin + 1, ymax - ymin + 1);
152}
153
154static void filter_metal(context_t *cx)
155{
156    static unsigned char const palette[] =
157    {
158        CUCUL_LIGHTBLUE, CUCUL_BLUE, CUCUL_LIGHTGRAY, CUCUL_DARKGRAY,
159    };
160
161    unsigned int x, y, w, h;
162
163    w = cucul_get_canvas_width(cx->torender);
164    h = cucul_get_canvas_height(cx->torender);
165
166    for(y = 0; y < h; y++)
167        for(x = 0; x < w; x++)
168    {
169        unsigned long int ch = cucul_get_char(cx->torender, x, y);
170        int i;
171
172        if(ch == (unsigned char)' ')
173            continue;
174
175        i = ((cx->lines + y + x / 8) / 2) % 4;
176        cucul_set_color_ansi(cx->torender, palette[i], CUCUL_TRANSPARENT);
177        cucul_put_char(cx->torender, x, y, ch);
178    }
179}
180
181static void filter_gay(context_t *cx)
182{
183    static unsigned char const rainbow[] =
184    {
185        CUCUL_LIGHTMAGENTA, CUCUL_LIGHTRED, CUCUL_YELLOW,
186        CUCUL_LIGHTGREEN, CUCUL_LIGHTCYAN, CUCUL_LIGHTBLUE,
187    };
188    unsigned int x, y, w, h;
189
190    w = cucul_get_canvas_width(cx->torender);
191    h = cucul_get_canvas_height(cx->torender);
192
193    for(y = 0; y < h; y++)
194        for(x = 0; x < w; x++)
195    {
196        unsigned long int ch = cucul_get_char(cx->torender, x, y);
197        if(ch != (unsigned char)' ')
198        {
199            cucul_set_color_ansi(cx->torender,
200                                 rainbow[(x / 2 + y + cx->lines) % 6],
201                                 CUCUL_TRANSPARENT);
202            cucul_put_char(cx->torender, x, y, ch);
203        }
204    }
205}
206
207static void filter_flip(context_t *cx)
208{
209    cucul_flip(cx->torender);
210}
211
212static void filter_flop(context_t *cx)
213{
214    cucul_flop(cx->torender);
215}
216
217static void filter_rotate(context_t *cx)
218{
219    cucul_rotate(cx->torender);
220}
221
Note: See TracBrowser for help on using the repository browser.