Browse Source

* src/bitmap.c:

+ Added antialiasing support.
    + Dithering, antialiasing and background mode can now be selected at
      runtime.
  * src/caca.c src/caca.h:
    + Renamed caca_dithering into caca_feature and extended the type to
      express background colour and antialiasing mode.
  * examples/demo.c:
    + Fixed a bug that disabled the sprite demo.
    + Draw solid flares.
  * examples/view.c:
    + Select antialiasing and background mode at runtime.
tags/v0.99.beta14
Sam Hocevar sam 21 years ago
parent
commit
d734f1d057
7 changed files with 430 additions and 298 deletions
  1. +0
    -1
      examples/aafire.c
  2. +7
    -11
      examples/demo.c
  3. +47
    -20
      examples/view.c
  4. +264
    -246
      src/bitmap.c
  5. +72
    -11
      src/caca.c
  6. +34
    -9
      src/caca.h
  7. +6
    -0
      src/caca_internals.h

+ 0
- 1
examples/aafire.c View File

@@ -133,7 +133,6 @@ initialize (void)
caca_bitmap = caca_create_bitmap(8, XSIZ, YSIZ - 2, XSIZ, 0, 0, 0, 0);
caca_set_bitmap_palette(caca_bitmap, r, g, b, a);
bitmap = malloc(XSIZ * YSIZ * sizeof(char));
caca_set_dithering(CACA_DITHERING_ORDERED8);
#else
aa_hidecursor (context);
#endif


+ 7
- 11
examples/demo.c View File

@@ -131,6 +131,7 @@ int main(int argc, char **argv)
case 'S':
if(sprite)
demo = demo_sprites;
break;
case 'r':
case 'R':
demo = demo_render;
@@ -501,7 +502,7 @@ static void demo_render(void)
struct caca_bitmap *bitmap;
int buffer[256*256];
int *dest;
int x, y, z, t, xo, yo;
int x, y, z, xo, yo;
static int i = 0;

i++;
@@ -510,31 +511,26 @@ static void demo_render(void)
for(x = 0; x < 256; x++)
for(y = 0; y < 256; y++)
{
*dest++ = 0;
*dest++ = 0xff000000;
}

/* red */
xo = 128 + 48 * sin(0.02 * i);
yo = 128 + 48 * cos(0.03 * i);
t = 256 * (2.0 + sin(4 + 0.017 * i)) / 3;
for(z = 0; z < 240; z++)
draw_circle(buffer, xo, yo, z, 0x00ff0000,
((255 - z) * t / 256) << 16);
draw_circle(buffer, xo, yo, z, 0x00ff0000, 200 << 16);

/* green */
xo = 128 + 48 * sin(2 + 0.06 * i);
yo = 128 + 48 * cos(2 + 0.05 * i);
t = 256 * (2.0 + sin(8 + 0.021 * i)) / 3;
for(z = 0; z < 240; z++)
draw_circle(buffer, xo, yo, z, 0x0000ff00,
((255 - z) * t / 256) << 8);
draw_circle(buffer, xo, yo, z, 0x0000ff00, 200 << 8);

/* blue */
xo = 128 + 48 * sin(1 + 0.04 * i);
yo = 128 + 48 * cos(1 + 0.03 * i);
t = 256 * (2.0 + sin(3 + 0.033 * i)) / 3;
for(z = 0; z < 240; z++)
draw_circle(buffer, xo, yo, z, 0x000000ff, (255 - z) * t / 256);
draw_circle(buffer, xo, yo, z, 0x000000ff, 200);

bitmap = caca_create_bitmap(32, 256, 256, 4 * 256, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
caca_draw_bitmap(0, 0, caca_get_width() - 1, caca_get_height() - 1,
@@ -547,7 +543,7 @@ static void draw_circle(int *buffer, int x, int y, int r, int mask, int val)
int t, dx, dy;

#define POINT(X,Y) \
buffer[(X) + 256 * (Y)] = (buffer[(X) + 256 * (Y)] & ~mask) | val;
buffer[(X) + 256 * (Y)] = 0xff000000 | (buffer[(X) + 256 * (Y)] & ~mask) | val;

for(t = 0, dx = 0, dy = r; dx <= dy; dx++)
{


+ 47
- 20
examples/view.c View File

@@ -46,7 +46,6 @@ int x, y, w, h;
int main(int argc, char **argv)
{
int quit = 0, update = 1, help = 0, reload = 0, fullscreen = 0, zoom = 0;
int dithering = CACA_DITHERING_ORDERED4;

char **list = NULL;
int current = 0, items = 0, opts = 1;
@@ -108,12 +107,40 @@ int main(int argc, char **argv)
fullscreen = ~fullscreen;
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'b':
i = 1 + caca_get_feature(CACA_BACKGROUND);
if(i > CACA_BACKGROUND_MAX) i = CACA_BACKGROUND_MIN;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'B':
i = -1 + caca_get_feature(CACA_BACKGROUND);
if(i < CACA_BACKGROUND_MIN) i = CACA_BACKGROUND_MAX;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'a':
i = 1 + caca_get_feature(CACA_ANTIALIASING);
if(i > CACA_ANTIALIASING_MAX) i = CACA_ANTIALIASING_MIN;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'A':
i = -1 + caca_get_feature(CACA_ANTIALIASING);
if(i < CACA_ANTIALIASING_MIN) i = CACA_ANTIALIASING_MAX;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'd':
dithering = (dithering + 1) % 5;
i = 1 + caca_get_feature(CACA_DITHERING);
if(i > CACA_DITHERING_MAX) i = CACA_DITHERING_MIN;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | 'D':
dithering = (dithering + 4) % 5;
i = -1 + caca_get_feature(CACA_DITHERING);
if(i < CACA_DITHERING_MIN) i = CACA_DITHERING_MAX;
caca_set_feature(i);
update = 1;
break;
case CACA_EVENT_KEY_PRESS | '+':
@@ -191,7 +218,6 @@ int main(int argc, char **argv)
}

caca_clear();
caca_set_dithering(dithering);
caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);

if(!items)
@@ -249,29 +275,30 @@ int main(int argc, char **argv)
{
caca_draw_line(0, 0, ww - 1, 0, ' ');
caca_draw_line(0, wh - 1, ww - 1, wh - 1, '-');
caca_putstr(0, 0, "q:Quit n/p:Next/Prev +/-/x:Zoom "
"h/j/k/l: Move d:Dithering");
caca_putstr(0, 0, "q:Quit np:Next/Prev +-x:Zoom "
"hjkl:Move d:Dithering a:Antialias");
caca_putstr(ww - strlen("?:Help"), 0, "?:Help");
caca_printf(3, wh - 1, "cacaview %s", VERSION);
caca_printf(ww / 2 - 5, wh - 1, "(%s dithering)",
caca_get_dithering_name(dithering));
caca_printf(3, wh - 1, "cacaview %s (%s, %s)", VERSION,
caca_get_feature_name(caca_get_feature(CACA_DITHERING)),
caca_get_feature_name(caca_get_feature(CACA_ANTIALIASING)));
caca_printf(ww - 14, wh - 1,
"(zoom: %s%i)", zoom > 0 ? "+" : "", zoom);
}

if(help)
{
caca_putstr(ww - 22, 2, " +: zoom in ");
caca_putstr(ww - 22, 3, " -: zoom out ");
caca_putstr(ww - 22, 4, " x: reset zoom ");
caca_putstr(ww - 22, 5, " ------------------- ");
caca_putstr(ww - 22, 6, " hjkl: move view ");
caca_putstr(ww - 22, 7, " arrows: move view ");
caca_putstr(ww - 22, 8, " ------------------- ");
caca_putstr(ww - 22, 9, " d: dithering method ");
caca_putstr(ww - 22, 10, " ------------------- ");
caca_putstr(ww - 22, 11, " ?: help ");
caca_putstr(ww - 22, 12, " q: quit ");
caca_putstr(ww - 22, 2, " +: zoom in ");
caca_putstr(ww - 22, 3, " -: zoom out ");
caca_putstr(ww - 22, 4, " x: reset zoom ");
caca_putstr(ww - 22, 5, " ---------------------- ");
caca_putstr(ww - 22, 6, " hjkl: move view ");
caca_putstr(ww - 22, 7, " arrows: move view ");
caca_putstr(ww - 22, 8, " ---------------------- ");
caca_putstr(ww - 22, 9, " a: antialiasing method ");
caca_putstr(ww - 22, 9, " d: dithering method ");
caca_putstr(ww - 22, 10, " ---------------------- ");
caca_putstr(ww - 22, 11, " ?: help ");
caca_putstr(ww - 22, 12, " q: quit ");

help = 0;
}


+ 264
- 246
src/bitmap.c View File

@@ -46,8 +46,16 @@ typedef unsigned int uint32_t;
#include "caca.h"
#include "caca_internals.h"

#define NEW_RENDERER 1
/*
* Global variables
*/
enum caca_feature _caca_background;
enum caca_feature _caca_dithering;
enum caca_feature _caca_antialiasing;

/*
* Local prototypes
*/
static void mask2shift(unsigned int, int *, int *);

static void get_rgba_default(const struct caca_bitmap *, uint8_t *, int, int,
@@ -76,54 +84,6 @@ static void init_random_dither(int);
static unsigned int get_random_dither(void);
static void increment_random_dither(void);

/* Current dithering method */
static enum caca_dithering _caca_dithering = CACA_DITHERING_NONE;

static void (*_init_dither) (int) = init_no_dither;
static unsigned int (*_get_dither) (void) = get_no_dither;
static void (*_increment_dither) (void) = increment_no_dither;

void caca_set_dithering(enum caca_dithering dither)
{
switch(dither)
{
case CACA_DITHERING_NONE:
_init_dither = init_no_dither;
_get_dither = get_no_dither;
_increment_dither = increment_no_dither;
break;

case CACA_DITHERING_ORDERED2:
_init_dither = init_ordered2_dither;
_get_dither = get_ordered2_dither;
_increment_dither = increment_ordered2_dither;
break;

case CACA_DITHERING_ORDERED4:
_init_dither = init_ordered4_dither;
_get_dither = get_ordered4_dither;
_increment_dither = increment_ordered4_dither;
break;

case CACA_DITHERING_ORDERED8:
_init_dither = init_ordered8_dither;
_get_dither = get_ordered8_dither;
_increment_dither = increment_ordered8_dither;
break;

case CACA_DITHERING_RANDOM:
_init_dither = init_random_dither;
_get_dither = get_random_dither;
_increment_dither = increment_random_dither;
break;

default:
return;
}

_caca_dithering = dither;
}

struct caca_bitmap
{
int bpp, palette;
@@ -287,17 +247,17 @@ static void get_rgba_default(const struct caca_bitmap *bitmap, uint8_t *pixels,

if(bitmap->palette)
{
*r = bitmap->red[bits];
*g = bitmap->green[bits];
*b = bitmap->blue[bits];
*a = bitmap->alpha[bits];
*r += bitmap->red[bits];
*g += bitmap->green[bits];
*b += bitmap->blue[bits];
*a += bitmap->alpha[bits];
}
else
{
*r = ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
*g = ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
*b = ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
*a = ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;
*r += ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
*g += ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
*b += ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
*a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;
}
}

@@ -334,7 +294,12 @@ static void rgb2hsv_default(int r, int g, int b, int *hue, int *sat, int *val)
void caca_draw_bitmap(int x1, int y1, int x2, int y2,
const struct caca_bitmap *bitmap, void *pixels)
{
#if !NEW_RENDERER
/* Current dithering method */
void (*_init_dither) (int);
unsigned int (*_get_dither) (void);
void (*_increment_dither) (void);

/* Only used when background is black */
static const int white_colors[] =
{
CACA_COLOR_BLACK,
@@ -342,7 +307,6 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
CACA_COLOR_LIGHTGRAY,
CACA_COLOR_WHITE
};
#endif

static const int light_colors[] =
{
@@ -403,222 +367,276 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2,
int tmp = y2; y2 = y1; y1 = tmp;
}

switch(_caca_dithering)
{
case CACA_DITHERING_NONE:
_init_dither = init_no_dither;
_get_dither = get_no_dither;
_increment_dither = increment_no_dither;
break;

case CACA_DITHERING_ORDERED2:
_init_dither = init_ordered2_dither;
_get_dither = get_ordered2_dither;
_increment_dither = increment_ordered2_dither;
break;

case CACA_DITHERING_ORDERED4:
_init_dither = init_ordered4_dither;
_get_dither = get_ordered4_dither;
_increment_dither = increment_ordered4_dither;
break;

case CACA_DITHERING_ORDERED8:
_init_dither = init_ordered8_dither;
_get_dither = get_ordered8_dither;
_increment_dither = increment_ordered8_dither;
break;

case CACA_DITHERING_RANDOM:
_init_dither = init_random_dither;
_get_dither = get_random_dither;
_increment_dither = increment_random_dither;
break;

default:
/* Something wicked happened! */
return;
}

for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++)
for(x = x1 > 0 ? x1 : 0, _init_dither(y);
x <= x2 && x <= (int)_caca_width;
x++)
{
int ch;
unsigned int r, g, b, a, R, G, B;
unsigned int r, g, b, a;
int hue, sat, val;
int fromx = w * (x - x1) / (x2 - x1 + 1);
int fromy = h * (y - y1) / (y2 - y1 + 1);
int fromx, fromy, tox, toy, myx, myy, dots;
enum caca_color outfg, outbg;
char outch;
#if NEW_RENDERER

/* Only used by coloured background */
int distbg, distfg, dist, hue1, hue2;
#endif

/* Clip values (yuck) */
if(fromx == 0) fromx = 1;
if(fromy == 0) fromy = 1;
r = g = b = a = 0;

/* First get RGB */
R = 0, G = 0, B = 0;
get_rgba_default(bitmap, pixels, fromx, fromy, &r, &g, &b, &a);
if(a == 0)
continue;
#if 1
R += r; G += g; B += b;
#else
R += r; G += g; B += b;
get_rgba_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b, &a);
R += r; G += g; B += b;
get_rgba_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b, &a);
R += r; G += g; B += b;
get_rgba_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b, &a);
R += r; G += g; B += b;
get_rgba_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b, &a);
R += r; G += g; B += b;
R /= 5; G /= 5; B /= 5;
#endif

/* Now get HSV from RGB */
rgb2hsv_default(R, G, B, &hue, &sat, &val);

/* The hard work: calculate foreground and background colours,
* as well as the most appropriate character to output. */
#if NEW_RENDERER
# define XRATIO 5*5
# define YRATIO 3*3
# define HRATIO 2*2
# define FUZZINESS XRATIO * 0x800

/* distance to black */
distbg = XRATIO * val * val;
distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
distbg = distbg * 2 / 4;
outbg = CACA_COLOR_BLACK;

/* distance to 30% */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 2;
if(dist <= distbg)
if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_DARKGRAY;
distbg = dist;
fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);
dots = 0;

for(myx = fromx; myx <= tox; myx++)
for(myy = fromy; myy <= toy; myy++)
{
dots++;
get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
}

/* Normalize */
r /= dots;
g /= dots;
b /= dots;
a /= dots;
}
else
{
outfg = CACA_COLOR_DARKGRAY;
distfg = dist;
}
fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);

/* check dist to 70% */
dist = XRATIO * (val - 0xa00) * (val - 0xa00)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_LIGHTGRAY;
distbg = dist;
}
else if(dist <= distfg)
{
outfg = CACA_COLOR_LIGHTGRAY;
distfg = dist;
}
myx = (fromx + tox) / 2;
myy = (fromy + toy) / 2;

/* check dist to white */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_WHITE;
distbg = dist;
}
else if(dist <= distfg)
{
outfg = CACA_COLOR_WHITE;
distfg = dist;
get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
}

hue1 = (hue + 0x800) & ~0xfff;
if(hue > hue1)
hue2 = (hue + 0x1800) & ~0xfff;
else
hue2 = (hue - 0x800) & ~0xfff;

/* check dist to 2nd closest dark color */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue2) * (hue - hue2);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
// dist = dist * 3 / 4;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = dark_colors[hue2 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = dark_colors[hue2 / 0x1000];
distfg = dist;
}
if(a < 0x100)
continue;

/* check dist to 2nd closest light color */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue2) * (hue - hue2);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
//dist = dist * 3 / 4;
//dist = dist / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = light_colors[hue2 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = light_colors[hue2 / 0x1000];
distfg = dist;
}
/* Now get HSV from RGB */
rgb2hsv_default(r, g, b, &hue, &sat, &val);

/* check dist to closest dark color */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue1) * (hue - hue1);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 4;
if(dist <= distbg)
/* The hard work: calculate foreground and background colours,
* as well as the most appropriate character to output. */
if(_caca_background == CACA_BACKGROUND_SOLID)
{
outfg = outbg;
distfg = distbg;
outbg = dark_colors[hue1 / 0x1000];
distbg = dist;
# define XRATIO 5*5
# define YRATIO 3*3
# define HRATIO 2*2
# define FUZZINESS XRATIO * 0x800

/* distance to black */
distbg = XRATIO * val * val;
distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
distbg = distbg * 2 / 4;
outbg = CACA_COLOR_BLACK;

/* distance to 30% */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_DARKGRAY;
distbg = dist;
}
else
{
outfg = CACA_COLOR_DARKGRAY;
distfg = dist;
}

/* check dist to 70% */
dist = XRATIO * (val - 0xa00) * (val - 0xa00)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_LIGHTGRAY;
distbg = dist;
}
else if(dist <= distfg)
{
outfg = CACA_COLOR_LIGHTGRAY;
distfg = dist;
}

/* check dist to white */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * sat * sat;
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = CACA_COLOR_WHITE;
distbg = dist;
}
else if(dist <= distfg)
{
outfg = CACA_COLOR_WHITE;
distfg = dist;
}

hue1 = (hue + 0x800) & ~0xfff;
if(hue > hue1)
hue2 = (hue + 0x1800) & ~0xfff;
else
hue2 = (hue - 0x800) & ~0xfff;

/* check dist to 2nd closest dark color */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue2) * (hue - hue2);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
//dist = dist * 3 / 4;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = dark_colors[hue2 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = dark_colors[hue2 / 0x1000];
distfg = dist;
}

/* check dist to 2nd closest light color */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue2) * (hue - hue2);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
//dist = dist * 3 / 4;
//dist = dist / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = light_colors[hue2 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = light_colors[hue2 / 0x1000];
distfg = dist;
}

/* check dist to closest dark color */
dist = XRATIO * (val - 0x600) * (val - 0x600)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue1) * (hue - hue1);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist * 3 / 4;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = dark_colors[hue1 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = dark_colors[hue1 / 0x1000];
distfg = dist;
}

/* check dist to closest light color */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue1) * (hue - hue1);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = light_colors[hue1 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = light_colors[hue1 / 0x1000];
distfg = dist;
}

if(distbg <= 0) distbg = 1;
if(distfg <= 0) distfg = 1;

/* distbg can be > distfg because of dithering fuzziness */
ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
ch = 4 * ch + _get_dither() / 0x40;
outch = density_chars[ch];
}
else if(dist <= distfg)
else
{
outfg = dark_colors[hue1 / 0x1000];
distfg = dist;
}
outbg = CACA_COLOR_BLACK;
if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10)
/ 0x1000];
else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
else
outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];

/* check dist to closest light color */
dist = XRATIO * (val - 0x1000) * (val - 0x1000)
+ YRATIO * (sat - 0x1000) * (sat - 0x1000)
+ HRATIO * (hue - hue1) * (hue - hue1);
dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
dist = dist / 2;
if(dist <= distbg)
{
outfg = outbg;
distfg = distbg;
outbg = light_colors[hue1 / 0x1000];
distbg = dist;
}
else if(dist <= distfg)
{
outfg = light_colors[hue1 / 0x1000];
distfg = dist;
ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
ch = 4 * ch + _get_dither() / 0x40;
outch = density_chars[ch];
}

if(distbg <= 0) distbg = 1;
if(distfg <= 0) distfg = 1;

/* distbg can be > distfg because of dithering fuzziness */
ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
ch = 4 * ch + _get_dither() / 0x40;
outch = density_chars[ch];

#else
outbg = CACA_COLOR_BLACK;
if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) / 0x1000];
else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
else
outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];

ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
ch = 4 * ch + _get_dither() / 0x40;
outch = density_chars[ch];

#endif

/* Now output the character */
caca_set_color(outfg, outbg);
caca_putchar(x, y, outch);


+ 72
- 11
src/caca.c View File

@@ -48,6 +48,7 @@
#include "caca.h"
#include "caca_internals.h"

static void caca_init_features(void);
static void caca_init_terminal(void);

#if defined(USE_NCURSES)
@@ -60,6 +61,7 @@ int caca_init(void)
mmask_t newmask;
#endif

caca_init_features();
caca_init_terminal();

#if defined(USE_SLANG)
@@ -156,21 +158,73 @@ const char *caca_get_color_name(enum caca_color color)
return color_names[color];
}

const char *caca_get_dithering_name(enum caca_dithering dithering)
enum caca_feature caca_get_feature(enum caca_feature feature)
{
static const char *dithering_names[] =
switch(feature)
{
"no",
"2x2 ordered",
"4x4 ordered",
"8x8 ordered",
"random"
};
case CACA_BACKGROUND:
return _caca_background;
case CACA_ANTIALIASING:
return _caca_antialiasing;
case CACA_DITHERING:
return _caca_dithering;

default:
return CACA_UNKNOWN_FEATURE;
}
}

if(dithering < 0 || dithering > 4)
return "unknown";
void caca_set_feature(enum caca_feature feature)
{
switch(feature)
{
case CACA_BACKGROUND:
feature = CACA_BACKGROUND_SOLID;
case CACA_BACKGROUND_BLACK:
case CACA_BACKGROUND_SOLID:
_caca_background = feature;
break;

case CACA_ANTIALIASING:
feature = CACA_ANTIALIASING_PREFILTER;
case CACA_ANTIALIASING_NONE:
case CACA_ANTIALIASING_PREFILTER:
_caca_antialiasing = feature;
break;

case CACA_DITHERING:
feature = CACA_DITHERING_ORDERED4;
case CACA_DITHERING_NONE:
case CACA_DITHERING_ORDERED2:
case CACA_DITHERING_ORDERED4:
case CACA_DITHERING_ORDERED8:
case CACA_DITHERING_RANDOM:
_caca_dithering = feature;
break;

case CACA_UNKNOWN_FEATURE:
break;
}
}

return dithering_names[dithering];
const char *caca_get_feature_name(enum caca_feature feature)
{
switch(feature)
{
case CACA_BACKGROUND_BLACK: return "black background";
case CACA_BACKGROUND_SOLID: return "solid background";

case CACA_ANTIALIASING_NONE: return "no antialiasing";
case CACA_ANTIALIASING_PREFILTER: return "prefilter antialiasing";

case CACA_DITHERING_NONE: return "no dithering";
case CACA_DITHERING_ORDERED2: return "2x2 ordered dithering";
case CACA_DITHERING_ORDERED4: return "4x4 ordered dithering";
case CACA_DITHERING_ORDERED8: return "8x8 ordered dithering";
case CACA_DITHERING_RANDOM: return "random dithering";

default: return "unknown";
}
}

void caca_end(void)
@@ -194,6 +248,13 @@ void caca_end(void)
#endif
}

static void caca_init_features(void)
{
caca_set_feature(CACA_BACKGROUND);
caca_set_feature(CACA_ANTIALIASING);
caca_set_feature(CACA_DITHERING);
}

static void caca_init_terminal(void)
{
#if defined(HAVE_GETENV) && defined(HAVE_PUTENV)


+ 34
- 9
src/caca.h View File

@@ -84,20 +84,44 @@ enum caca_color
const char *caca_get_color_name(enum caca_color);

/**
* The dithering modes to be used with caca_set_dithering().
* The internal libcaca features.
*/
enum caca_dithering
enum caca_feature
{
CACA_DITHERING_NONE = 0,
CACA_DITHERING_ORDERED2 = 1,
CACA_DITHERING_ORDERED4 = 2,
CACA_DITHERING_ORDERED8 = 3,
CACA_DITHERING_RANDOM = 4
/* Properties of background characters */
CACA_BACKGROUND = 0x10,
CACA_BACKGROUND_BLACK = 0x11,
CACA_BACKGROUND_SOLID = 0x12,
#define CACA_BACKGROUND_MIN 0x11
#define CACA_BACKGROUND_MAX 0x12

/* Antialiasing features */
CACA_ANTIALIASING = 0x20,
CACA_ANTIALIASING_NONE = 0x21,
CACA_ANTIALIASING_PREFILTER = 0x22,
#define CACA_ANTIALIASING_MIN 0x21
#define CACA_ANTIALIASING_MAX 0x22

/* Dithering methods */
CACA_DITHERING = 0x30,
CACA_DITHERING_NONE = 0x31,
CACA_DITHERING_ORDERED2 = 0x32,
CACA_DITHERING_ORDERED4 = 0x33,
CACA_DITHERING_ORDERED8 = 0x34,
CACA_DITHERING_RANDOM = 0x35,
#define CACA_DITHERING_MIN 0x31
#define CACA_DITHERING_MAX 0x35

/* Unknown feature */
CACA_UNKNOWN_FEATURE = 0xffff
};

const char *caca_get_dithering_name(enum caca_dithering);
const char *caca_get_feature_name(enum caca_feature);

/* Backwards compatibility */
#define caca_dithering caca_feature
#define caca_set_dithering caca_set_feature
#define caca_get_dithering_name caca_get_feature_name
#define CACA_DITHER_NONE CACA_DITHERING_NONE
#define CACA_DITHER_ORDERED CACA_DITHERING_ORDERED8
#define CACA_DITHER_RANDOM CACA_DITHERING_RANDOM
@@ -145,7 +169,8 @@ enum caca_key
*/
int caca_init(void);
void caca_set_delay(unsigned int);
void caca_set_dithering(enum caca_dithering);
enum caca_feature caca_get_feature(enum caca_feature);
void caca_set_feature(enum caca_feature);
unsigned int caca_get_rendertime(void);
unsigned int caca_get_width(void);
unsigned int caca_get_height(void);


+ 6
- 0
src/caca_internals.h View File

@@ -32,7 +32,13 @@

extern int _caca_init_graphics(void);

/* Cached screen size */
extern unsigned int _caca_width;
extern unsigned int _caca_height;

/* Internal libcaca features */
extern enum caca_feature _caca_background;
extern enum caca_feature _caca_dithering;
extern enum caca_feature _caca_antialiasing;

#endif /* __CACA_INTERNALS_H__ */

Loading…
Cancel
Save