+ Dither chroma outside of rgb2hsv_default().
+ Clip fromx and fromy values.
* NOTES:
+ Link to the XTerm control sequences.
* examples/view.c:
+ Draw status bar.
+ Move with 'h' 'j' 'k' 'l', à la vi.
+ '?' toggles a help menu.
tags/v0.99.beta14
| @@ -17,11 +17,12 @@ $Id$ | |||||
| setab=\E[4%p1%dm, setaf=\E[3%p1%dm | setab=\E[4%p1%dm, setaf=\E[3%p1%dm | ||||
| From the xterm-16color terminfo: | From the xterm-16color terminfo: | ||||
| (http://www.sct.gu.edu.au/~anthony/info/X/Xterm_xf86.terminfo) | |||||
| setab=\E[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm, | setab=\E[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm, | ||||
| setaf=\E[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm, | setaf=\E[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm, | ||||
| (http://www.sct.gu.edu.au/~anthony/info/X/Xterm_xf86.terminfo) | |||||
| These values can be simply retrieved with a tigetstr() call. | |||||
| o I tested the following terminals: | o I tested the following terminals: | ||||
| @@ -75,9 +76,11 @@ $Id$ | |||||
| + gnome-terminal (no bright bg) | + gnome-terminal (no bright bg) | ||||
| + konsole (no bright bg, $blink really blinks) | + konsole (no bright bg, $blink really blinks) | ||||
| o In an XTerm-compatible terminal, \e[9xm sets bright foreground and | |||||
| \e[10xm bright background colours. Unfortunately all terminals don't | |||||
| support these escape sequences. Here is a testcase: | |||||
| o In an XTerm-compatible terminal, \e[9xm sets bright foreground | |||||
| and \e[10xm bright background colours. Documentation on this can be | |||||
| found at http://ftp.xfree86.org/pub/XFree86/4.2.1/doc/ctlseqs.TXT . | |||||
| Unfortunately all terminals don't support these escape sequences. Here | |||||
| is a testcase: | |||||
| for fgpre in 3 9; do for fg in 0 4 2 6 1 5 3 7; do | for fgpre in 3 9; do for fg in 0 4 2 6 1 5 3 7; do | ||||
| for bgpre in 4 10; do | for bgpre in 4 10; do | ||||
| @@ -24,6 +24,7 @@ | |||||
| #include "config.h" | #include "config.h" | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <string.h> | |||||
| #define X_DISPLAY_MISSING 1 | #define X_DISPLAY_MISSING 1 | ||||
| #include <Imlib2.h> | #include <Imlib2.h> | ||||
| @@ -40,7 +41,7 @@ const enum caca_dithering dithering_list[] = | |||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||
| { | { | ||||
| int quit = 0, update = 1; | |||||
| int quit = 0, update = 1, help = 0; | |||||
| int x, y, w, h, zoom = 0; | int x, y, w, h, zoom = 0; | ||||
| if(argc != 2) | if(argc != 2) | ||||
| @@ -108,22 +109,34 @@ int main(int argc, char **argv) | |||||
| zoom = 0; | zoom = 0; | ||||
| update = 1; | update = 1; | ||||
| break; | break; | ||||
| case CACA_EVENT_KEY_PRESS | 'k': | |||||
| case CACA_EVENT_KEY_PRESS | 'K': | |||||
| case CACA_EVENT_KEY_PRESS | CACA_KEY_UP: | case CACA_EVENT_KEY_PRESS | CACA_KEY_UP: | ||||
| if(zoom > 0) y -= 1 + h / (2 + zoom) / 8; | if(zoom > 0) y -= 1 + h / (2 + zoom) / 8; | ||||
| update = 1; | update = 1; | ||||
| break; | break; | ||||
| case CACA_EVENT_KEY_PRESS | 'j': | |||||
| case CACA_EVENT_KEY_PRESS | 'J': | |||||
| case CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN: | case CACA_EVENT_KEY_PRESS | CACA_KEY_DOWN: | ||||
| if(zoom > 0) y += 1 + h / (2 + zoom) / 8; | if(zoom > 0) y += 1 + h / (2 + zoom) / 8; | ||||
| update = 1; | update = 1; | ||||
| break; | break; | ||||
| case CACA_EVENT_KEY_PRESS | 'h': | |||||
| case CACA_EVENT_KEY_PRESS | 'H': | |||||
| case CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT: | case CACA_EVENT_KEY_PRESS | CACA_KEY_LEFT: | ||||
| if(zoom > 0) x -= 1 + w / (2 + zoom) / 8; | if(zoom > 0) x -= 1 + w / (2 + zoom) / 8; | ||||
| update = 1; | update = 1; | ||||
| break; | break; | ||||
| case CACA_EVENT_KEY_PRESS | 'l': | |||||
| case CACA_EVENT_KEY_PRESS | 'L': | |||||
| case CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT: | case CACA_EVENT_KEY_PRESS | CACA_KEY_RIGHT: | ||||
| if(zoom > 0) x += 1 + w / (2 + zoom) / 8; | if(zoom > 0) x += 1 + w / (2 + zoom) / 8; | ||||
| update = 1; | update = 1; | ||||
| break; | break; | ||||
| case CACA_EVENT_KEY_PRESS | '?': | |||||
| help = !help; | |||||
| update = 1; | |||||
| break; | |||||
| case CACA_EVENT_KEY_PRESS | 'q': | case CACA_EVENT_KEY_PRESS | 'q': | ||||
| case CACA_EVENT_KEY_PRESS | 'Q': | case CACA_EVENT_KEY_PRESS | 'Q': | ||||
| quit = 1; | quit = 1; | ||||
| @@ -133,14 +146,17 @@ int main(int argc, char **argv) | |||||
| if(update) | if(update) | ||||
| { | { | ||||
| int ww = caca_get_width(); | |||||
| int wh = caca_get_height(); | |||||
| caca_clear(); | caca_clear(); | ||||
| caca_set_dithering(dithering_list[dithering]); | caca_set_dithering(dithering_list[dithering]); | ||||
| if(zoom < 0) | if(zoom < 0) | ||||
| { | { | ||||
| int xo = (caca_get_width() - 1) / 2; | |||||
| int yo = (caca_get_height() - 1) / 2; | |||||
| int xn = (caca_get_width() - 1) / (2 - zoom); | |||||
| int yn = (caca_get_height() - 1) / (2 - zoom); | |||||
| int xo = (ww - 1) / 2; | |||||
| int yo = (wh - 1) / 2; | |||||
| int xn = (ww - 1) / (2 - zoom); | |||||
| int yn = (wh - 1) / (2 - zoom); | |||||
| caca_draw_bitmap(xo - xn, yo - yn, xo + xn, yo + yn, | caca_draw_bitmap(xo - xn, yo - yn, xo + xn, yo + yn, | ||||
| bitmap, pixels); | bitmap, pixels); | ||||
| } | } | ||||
| @@ -154,17 +170,39 @@ int main(int argc, char **argv) | |||||
| if(xn + x > w) x = w - xn; | if(xn + x > w) x = w - xn; | ||||
| if(yn + y > h) y = h - yn; | if(yn + y > h) y = h - yn; | ||||
| newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w, | newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w, | ||||
| 0x00ff0000, 0x0000ff00, 0x000000ff); | |||||
| caca_draw_bitmap(0, 0, caca_get_width() - 1, | |||||
| caca_get_height() - 1, newbitmap, | |||||
| 0x00ff0000, 0x0000ff00, 0x000000ff); | |||||
| caca_draw_bitmap(0, 0, ww - 1, wh - 1, newbitmap, | |||||
| pixels + 4 * (x - xn) + 4 * w * (y - yn)); | pixels + 4 * (x - xn) + 4 * w * (y - yn)); | ||||
| caca_free_bitmap(newbitmap); | caca_free_bitmap(newbitmap); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| caca_draw_bitmap(0, 0, caca_get_width() - 1, | |||||
| caca_get_height() - 1, bitmap, pixels); | |||||
| caca_draw_bitmap(0, 0, ww - 1, wh - 1, bitmap, pixels); | |||||
| } | |||||
| caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); | |||||
| caca_draw_line(0, 0, ww - 1, 0, ' '); | |||||
| caca_printf(1, 0, "cacaview %s", VERSION); | |||||
| caca_putstr(ww - strlen("'?' for help") - 1, 0, | |||||
| "'?' for help"); | |||||
| if(help) | |||||
| { | |||||
| caca_putstr(2, 2, " +: zoom in "); | |||||
| caca_putstr(2, 3, " -: zoom out "); | |||||
| caca_putstr(2, 4, " x: reset zoom "); | |||||
| caca_putstr(2, 5, " ------------------- "); | |||||
| caca_putstr(2, 6, " hjkl: move view "); | |||||
| caca_putstr(2, 7, " arrows: move view "); | |||||
| caca_putstr(2, 8, " ------------------- "); | |||||
| caca_putstr(2, 9, " d: dithering method "); | |||||
| caca_putstr(2, 10, " ------------------- "); | |||||
| caca_putstr(2, 11, " ?: help "); | |||||
| caca_putstr(2, 12, " q: quit "); | |||||
| help = 0; | |||||
| } | } | ||||
| caca_refresh(); | caca_refresh(); | ||||
| update = 0; | update = 0; | ||||
| } | } | ||||
| @@ -221,9 +221,7 @@ static void get_rgb_default(struct caca_bitmap *bitmap, unsigned char *pixels, | |||||
| bits = *(uint32_t *)(pixels + 0); | bits = *(uint32_t *)(pixels + 0); | ||||
| break; | break; | ||||
| case 3: | case 3: | ||||
| bits = (pixels[0] << 16) | |||||
| | (pixels[1] << 8) | |||||
| | (pixels[2]); | |||||
| bits = (pixels[0] << 16) | (pixels[1] << 8) | (pixels[2]); | |||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| bits = *(uint16_t *)(pixels + 0); | bits = *(uint16_t *)(pixels + 0); | ||||
| @@ -256,27 +254,25 @@ static void rgb2hsv_default(int r, int g, int b, int *hue, int *sat, int *val) | |||||
| if(min > g) min = g; if(max < g) max = g; | if(min > g) min = g; if(max < g) max = g; | ||||
| if(min > b) min = b; if(max < b) max = b; | if(min > b) min = b; if(max < b) max = b; | ||||
| delta = max - min; /* 0 - 65535 */ | |||||
| *val = max; /* 0 - 65535 */ | |||||
| *sat = max ? 0x100 * delta / max * 0x100: 0; /* 0 - 65536 */ | |||||
| delta = max - min; /* 0 - 0xffff */ | |||||
| *val = max; /* 0 - 0xffff */ | |||||
| if(*sat > (_get_dither() + 24) * 0x400) | |||||
| if(delta) | |||||
| { | { | ||||
| /* XXX: Values should be between 1 and 6, but since we | |||||
| * are dithering, there may be overflows, hence our bigger | |||||
| * *_colors[] tables. */ | |||||
| *sat = 0x1000 * delta / max * 0x10; /* 0 - 0xffff */ | |||||
| /* Generate *hue between 0 and 0x5ffff */ | |||||
| if( r == max ) | if( r == max ) | ||||
| *hue = 0x10000 + 0x100 * (g - b) / delta * 0x100; | *hue = 0x10000 + 0x100 * (g - b) / delta * 0x100; | ||||
| else if( g == max ) | else if( g == max ) | ||||
| *hue = 0x30000 + 0x100 * (b - r) / delta * 0x100; | *hue = 0x30000 + 0x100 * (b - r) / delta * 0x100; | ||||
| else | else | ||||
| *hue = 0x50000 + 0x100 * (r - g) / delta * 0x100; | *hue = 0x50000 + 0x100 * (r - g) / delta * 0x100; | ||||
| *hue = (*hue + 0x8000 + 0x1000 * _get_dither()) / 0x10000; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| *sat = 0; | *sat = 0; | ||||
| *hue = 0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -360,6 +356,10 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, | |||||
| int fromx = w * (x - x1) / (x2 - x1 + 1); | int fromx = w * (x - x1) / (x2 - x1 + 1); | ||||
| int fromy = h * (y - y1) / (y2 - y1 + 1); | int fromy = h * (y - y1) / (y2 - y1 + 1); | ||||
| /* Clip values (yuck) */ | |||||
| if(fromx == 0) fromx = 1; | |||||
| if(fromy == 0) fromy = 1; | |||||
| /* First get RGB */ | /* First get RGB */ | ||||
| R = 0, G = 0, B = 0; | R = 0, G = 0, B = 0; | ||||
| get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b); | get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b); | ||||
| @@ -377,12 +377,12 @@ void caca_draw_bitmap(int x1, int y1, int x2, int y2, | |||||
| /* Now get HSV from RGB */ | /* Now get HSV from RGB */ | ||||
| rgb2hsv_default(R, G, B, &hue, &sat, &val); | rgb2hsv_default(R, G, B, &hue, &sat, &val); | ||||
| if(!sat) | |||||
| if(sat < 0x6000 + _get_dither() * 0x800) | |||||
| caca_set_color(white_colors[val * 3 / 0x10000], CACA_COLOR_BLACK); | caca_set_color(white_colors[val * 3 / 0x10000], CACA_COLOR_BLACK); | ||||
| else if(val > (_get_dither() + 40) * 0x400) | else if(val > (_get_dither() + 40) * 0x400) | ||||
| caca_set_color(light_colors[hue], CACA_COLOR_BLACK); | |||||
| caca_set_color(light_colors[(hue + 0x8000 + _get_dither() * 0x1000) / 0x10000], CACA_COLOR_BLACK); | |||||
| else | else | ||||
| caca_set_color(dark_colors[hue], CACA_COLOR_BLACK); | |||||
| caca_set_color(dark_colors[(hue + 0x8000 + _get_dither() * 0x1000) / 0x10000], CACA_COLOR_BLACK); | |||||
| /* FIXME: choose better characters! */ | /* FIXME: choose better characters! */ | ||||
| ch = (val + 0x200 * _get_dither()) * 10 / 0x10000; | ch = (val + 0x200 * _get_dither()) * 10 / 0x10000; | ||||