Browse Source

* src/blit.c:

+ Hue calculation now uses integers only.
    + Dithering is now parametrable. Implemented none, ordered, random.
  * examples/demo.c:
    + Added dithering selection.
tags/v0.99.beta14
Sam Hocevar sam 21 years ago
parent
commit
547f38ca4e
3 changed files with 148 additions and 16 deletions
  1. +17
    -2
      examples/demo.c
  2. +128
    -12
      src/blit.c
  3. +3
    -2
      src/caca.h

+ 17
- 2
examples/demo.c View File

@@ -47,6 +47,7 @@ static void demo_blit(void);

int bounds = 0;
int outline = 0;
int dithering = 0;
struct caca_sprite *sprite = NULL;

GdkPixbuf *pixbuf;
@@ -76,10 +77,13 @@ gdk_init (&argc, &argv);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/union.png", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/pikachu.jpeg", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/gradient.png", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/beastie.png", NULL);
pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/stitch.jpg", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/pix/dranac.jpeg", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/artwork/aboire.png", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/web/sam.zoy.org/artwork/goret.png", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/lilkim02.jpg", NULL);
pixbuf = gdk_pixbuf_new_from_file("/home/sam/etw.bmp", NULL);
//pixbuf = gdk_pixbuf_new_from_file("/home/sam/etw.bmp", NULL);
if(!pixbuf) return -2;
pixels = gdk_pixbuf_get_pixels(pixbuf);
bufx = gdk_pixbuf_get_width(pixbuf);
@@ -123,6 +127,14 @@ fprintf(stderr, "w %i, h %i, stride %i\n", bufx, bufy, bufpitch);
bounds = (bounds + 1) % 2;
display_menu();
break;
case 'd':
case 'D':
dithering = (dithering + 1) % 3;
caca_set_dithering(dithering == 0 ? CACA_DITHER_NONE :
dithering == 1 ? CACA_DITHER_ORDERED :
CACA_DITHER_RANDOM);
display_menu();
break;
case 'c':
demo = demo_color;
break;
@@ -213,6 +225,8 @@ static void display_menu(void)
outline == 0 ? "none" : outline == 1 ? "solid" : "thin");
caca_printf(4, 19, "'b': drawing boundaries: %s",
bounds == 0 ? "screen" : "infinite");
caca_printf(4, 20, "'d': %s dithering",
dithering == 0 ? "no" : dithering == 1 ? "ordered" : "random");

caca_putstr(4, yo - 2, "'q': quit");
}
@@ -464,6 +478,7 @@ static void demo_sprites(void)

static void demo_blit(void)
{
caca_blit(6, 4, caca_get_width() - 6, caca_get_height() - 4, pixels, bufx, bufy);
caca_blit(6, 4, caca_get_width() - 6, caca_get_height() - 4,
pixels, bufx, bufy);
}


+ 128
- 12
src/blit.c View File

@@ -34,19 +34,60 @@ typedef unsigned char uint8_t;
#include "caca.h"
#include "caca_internals.h"

/* Dithering methods */
static void init_no_dither(int);
static int get_no_dither(void);
static void increment_no_dither(void);

static void init_ordered_dither(int);
static int get_ordered_dither(void);
static void increment_ordered_dither(void);

static void init_random_dither(int);
static int get_random_dither(void);
static void increment_random_dither(void);

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

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

void caca_set_dithering(enum caca_dithering dither)
{
if(dither < 0 || dither > 1)
switch(dither)
{
case CACA_DITHER_NONE:
_init_dither = init_no_dither;
_get_dither = get_no_dither;
_increment_dither = increment_no_dither;
break;

case CACA_DITHER_ORDERED:
_init_dither = init_ordered_dither;
_get_dither = get_ordered_dither;
_increment_dither = increment_ordered_dither;
break;

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

default:
return;
}

_caca_dithering = dither;
}

void caca_blit(int x1, int y1, int x2, int y2, void *pixels, int w, int h)
{
char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
static int light_colors[] = {CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_YELLOW, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTMAGENTA};
static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN, CACA_COLOR_GREEN, CACA_COLOR_CYAN, CACA_COLOR_BLUE, CACA_COLOR_MAGENTA};
static char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
int x, y, pitch;

if(x1 > x2)
@@ -62,10 +103,13 @@ void caca_blit(int x1, int y1, int x2, int y2, void *pixels, int w, int h)
pitch = (3 * w + 3) / 4 * 4;

for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)caca_get_height(); y++)
{
/* Initialize dither tables for the current line */
_init_dither(y);

/* Dither the current line */
for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
{
static int light_colors[] = {CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_YELLOW, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTMAGENTA};
static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN, CACA_COLOR_GREEN, CACA_COLOR_CYAN, CACA_COLOR_BLUE, CACA_COLOR_MAGENTA};
int fromx = w * (x - x1) / (x2 - x1 + 1);
int fromy = h * (y - y1) / (y2 - y1 + 1);
int r = ((unsigned char *)pixels)[3 * fromx + pitch * fromy];
@@ -81,18 +125,21 @@ static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN
val = max; /* 0 - 255 */
sat = max ? 256 * delta / max : 0; /* 0 - 255 */

if(sat > caca_rand(64, 128))
if(sat > (_get_dither() + 24) * 4)
{
/* XXX: Values are automatically clipped between 0 and 6
* because of delta/2 */
/* XXX: Values should be between 1 and 6, but since we
* are dithering, there may be overflows, hence our bigger
* *_colors[] tables. */
if( r == max )
hue = 1 + (float)(g - b + delta / 2 + caca_rand(-40, 40)) / delta;
hue = 256 + 256 * (g - b) / delta;
else if( g == max )
hue = 3 + (float)(b - r + delta / 2 + caca_rand(-40, 40)) / delta;
hue = 768 + 256 * (b - r) / delta;
else
hue = 5 + (float)(r - g + delta / 2 + caca_rand(-40, 40)) / delta;
hue = 1280 + 256 * (r - g) / delta;

hue = (hue + 128 + 8 * _get_dither()) / 256;

if(val > caca_rand(128, 192))
if(val > (_get_dither() + 40) * 4)
caca_set_color(light_colors[hue]);
else
caca_set_color(dark_colors[hue]);
@@ -102,7 +149,76 @@ static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN
caca_set_color(CACA_COLOR_LIGHTGRAY);
}

caca_putchar(x, y, foo[(r + g + b + caca_rand(-10, 10)) / 3 / 25]);
caca_putchar(x, y, foo[(r + g + b + 2 * _get_dither()) / 3 / 25]);

_increment_dither();
}
}
}

/*
* XXX: The following functions are local.
*/

/*
* No dithering
*/
static void init_no_dither(int line)
{
;
}

static int get_no_dither(void)
{
return 0;
}

static void increment_no_dither(void)
{
return;
}

/*
* Ordered dithering
*/
static int dither4x4[] = {-8, 0, -6, 2,
4, -4, 6, -2,
-5, 3, -7, 1,
7, -1, 5, -3};
static int *dither_table;
static int dither_index;

static void init_ordered_dither(int line)
{
dither_table = dither4x4 + (line % 4) * 4;
dither_index = 0;
}

static int get_ordered_dither(void)
{
return dither_table[dither_index];
}

static void increment_ordered_dither(void)
{
dither_index = (dither_index + 1) % 4;
}

/*
* Random dithering
*/
static void init_random_dither(int line)
{
;
}

static int get_random_dither(void)
{
return caca_rand(-8, 7);
}

static void increment_random_dither(void)
{
return;
}


+ 3
- 2
src/caca.h View File

@@ -57,8 +57,9 @@ enum caca_color
*/
enum caca_dithering
{
CACA_DITHER_NONE = 0,
CACA_DITHER_RANDOM = 1
CACA_DITHER_NONE,
CACA_DITHER_ORDERED,
CACA_DITHER_RANDOM
};

/*


Loading…
Cancel
Save