diff --git a/src/bitmap.c b/src/bitmap.c index 423ed02..5c549a9 100644 --- a/src/bitmap.c +++ b/src/bitmap.c @@ -42,6 +42,8 @@ typedef unsigned int uint32_t; #include "caca.h" #include "caca_internals.h" +#define NEW_RENDERER 1 + static void mask2shift(unsigned int, int *, int *); static void get_rgb_default(struct caca_bitmap *, uint8_t *, int, int, @@ -308,16 +310,17 @@ 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, struct caca_bitmap *bitmap, char *pixels) { - /* FIXME: this code is shite! */ - static int white_colors[] = +#if !NEW_RENDERER + static const int white_colors[] = { CACA_COLOR_BLACK, CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE }; +#endif - static int light_colors[] = + static const int light_colors[] = { CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, @@ -328,7 +331,7 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, CACA_COLOR_LIGHTMAGENTA }; - static int dark_colors[] = + static const int dark_colors[] = { CACA_COLOR_MAGENTA, CACA_COLOR_RED, @@ -341,7 +344,7 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* FIXME: choose better characters! */ # define DENSITY_CHARS 13 - static char density_chars[] = + static const char density_chars[] = " " " " ".` " @@ -388,9 +391,8 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, int fromy = h * (y - y1) / (y2 - y1 + 1); enum caca_color outfg, outbg; char outch; -#define NEW_DITHERER 1 -#ifdef NEW_DITHERER - int distbg, distfg, dist; +#if NEW_RENDERER + int distbg, distfg, dist, hue1, hue2; #endif /* Clip values (yuck) */ @@ -400,7 +402,9 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* First get RGB */ R = 0, G = 0, B = 0; get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b); -#if 0 +#if 1 + R += r; G += g; B += b; +#else R += r; G += g; B += b; get_rgb_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b); R += r; G += g; B += b; @@ -411,8 +415,6 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, get_rgb_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b); R += r; G += g; B += b; R /= 5; G /= 5; B /= 5; -#else - R += r; G += g; B += b; #endif /* Now get HSV from RGB */ @@ -420,18 +422,22 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* The hard work: calculate foreground and background colours, * as well as the most appropriate character to output. */ -#if NEW_DITHERER -#define XRATIO 5*5 -#define YRATIO 3*3 +#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 += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; outbg = CACA_COLOR_BLACK; /* distance to 30% */ dist = XRATIO * (val - 0x600) * (val - 0x600) + YRATIO * sat * sat; - dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; + dist = dist * 3 / 2; if(dist <= distbg) { outfg = outbg; @@ -448,7 +454,8 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* check dist to 70% */ dist = XRATIO * (val - 0xa00) * (val - 0xa00) + YRATIO * sat * sat; - dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; + dist = dist * 3 / 2; if(dist <= distbg) { outfg = outbg; @@ -465,7 +472,7 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* check dist to white */ dist = XRATIO * (val - 0x1000) * (val - 0x1000) + YRATIO * sat * sat; - dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; if(dist <= distbg) { outfg = outbg; @@ -479,39 +486,85 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, distfg = dist; } - /* check dist to dark */ + 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); - dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + + 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[(hue + _get_dither() * 0x10) / 0x1000]; + outbg = dark_colors[hue2 / 0x1000]; distbg = dist; } else if(dist <= distfg) { - outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000]; + outfg = dark_colors[hue2 / 0x1000]; distfg = dist; } - /* check dist to light */ + /* check dist to 2nd closest light color */ dist = XRATIO * (val - 0x1000) * (val - 0x1000) - + YRATIO * (sat - 0x1000) * (sat - 0x1000); - dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000; + + YRATIO * (sat - 0x1000) * (sat - 0x1000) + + HRATIO * (hue - hue2) * (hue - hue2); + dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; dist = dist / 2; if(dist <= distbg) { outfg = outbg; distfg = distbg; - outbg = light_colors[(hue + _get_dither() * 0x10) / 0x1000]; + outbg = light_colors[hue2 / 0x1000]; distbg = dist; } else if(dist <= distfg) { - outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000]; + 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; } @@ -520,14 +573,14 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, /* distbg can be > distfg because of dithering fuzziness */ ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg); - ch = 4 * ch /*+ _get_dither() / 0x40*/; + ch = 4 * ch + _get_dither() / 0x40; outch = density_chars[ch]; #else outbg = CACA_COLOR_BLACK; - if(sat < 0x200 + _get_dither() * 0x8) + if((unsigned int)sat < 0x200 + _get_dither() * 0x8) outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) / 0x1000]; - else if(val > 0x800 + _get_dither() * 0x4) + 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];