diff --git a/examples/Makefile.am b/examples/Makefile.am index 976873b..8dd4fa5 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -20,12 +20,15 @@ caca_spritedit_SOURCES = spritedit.c caca_spritedit_LDADD = ../src/libcaca.a @CACA_LIBS@ caca_spritedit_CPPFLAGS = -I$(top_srcdir)/src -if USE_IMLIB2 cacaview = cacaview cacaview_SOURCES = view.c cacaview_LDADD = ../src/libcaca.a @CACA_LIBS@ cacaview_CPPFLAGS = -I$(top_srcdir)/src -DX_DISPLAY_MISSING=1 +if USE_IMLIB2 cacaview_CFLAGS = `imlib2-config --cflags` cacaview_LDFLAGS = `imlib2-config --libs` +else +cacaview_CFLAGS = +cacaview_LDFLAGS = endif diff --git a/examples/view.c b/examples/view.c index a09db88..fb133db 100644 --- a/examples/view.c +++ b/examples/view.c @@ -28,24 +28,44 @@ #include #include -#include +#if defined(HAVE_IMLIB2_H) +# include +#else +# include +#endif #include "caca.h" +/* Local macros */ +#define STATUS_DITHERING 1 +#define STATUS_ANTIALIASING 2 +#define STATUS_BACKGROUND 3 + /* Local functions */ static void load_image(const char *); +static void unload_image(void); static void draw_checkers(unsigned int, unsigned int, unsigned int, unsigned int); +#if !defined(HAVE_IMLIB2_H) +static int freadint(FILE *); +static int freadshort(FILE *); +static int freadchar(FILE *); +#endif /* Local variables */ +#if defined(HAVE_IMLIB2_H) Imlib_Image image = NULL; +#endif char *pixels = NULL; struct caca_bitmap *bitmap = NULL; -int x, y, w, h; +int x, y; +unsigned int w, h, depth, bpp, rmask, gmask, bmask, amask; +unsigned int red[256], green[256], blue[256], alpha[256]; int main(int argc, char **argv) { - int quit = 0, update = 1, help = 0, reload = 0, fullscreen = 0, zoom = 0; + int quit = 0, update = 1, help = 0, fullscreen = 0, status = 0; + int reload = 0, zoom = 0; char **list = NULL; int current = 0, items = 0, opts = 1; @@ -86,7 +106,7 @@ int main(int argc, char **argv) int ww = caca_get_width(); int wh = caca_get_height(); - int event; + int event, new_status = 0, new_help = 0; while((event = caca_get_event())) { @@ -111,36 +131,42 @@ int main(int argc, char **argv) i = 1 + caca_get_feature(CACA_BACKGROUND); if(i > CACA_BACKGROUND_MAX) i = CACA_BACKGROUND_MIN; caca_set_feature(i); + new_status = STATUS_BACKGROUND; 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); + new_status = STATUS_BACKGROUND; 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); + new_status = STATUS_ANTIALIASING; 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); + new_status = STATUS_ANTIALIASING; update = 1; break; case CACA_EVENT_KEY_PRESS | 'd': i = 1 + caca_get_feature(CACA_DITHERING); if(i > CACA_DITHERING_MAX) i = CACA_DITHERING_MIN; caca_set_feature(i); + new_status = STATUS_DITHERING; update = 1; break; case CACA_EVENT_KEY_PRESS | 'D': i = -1 + caca_get_feature(CACA_DITHERING); if(i < CACA_DITHERING_MIN) i = CACA_DITHERING_MAX; caca_set_feature(i); + new_status = STATUS_DITHERING; update = 1; break; case CACA_EVENT_KEY_PRESS | '+': @@ -181,7 +207,7 @@ int main(int argc, char **argv) update = 1; break; case CACA_EVENT_KEY_PRESS | '?': - help = 1; + new_help = !help; update = 1; break; case CACA_EVENT_KEY_PRESS | 'q': @@ -189,6 +215,12 @@ int main(int argc, char **argv) quit = 1; break; } + + if(status || new_status) + status = new_status; + + if(help || new_help) + help = new_help; } if(items && reload) @@ -204,6 +236,7 @@ int main(int argc, char **argv) caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer); caca_refresh(); + unload_image(); load_image(list[current]); reload = 0; update = 1; @@ -218,15 +251,18 @@ int main(int argc, char **argv) } caca_clear(); - caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); if(!items) + { + caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); caca_printf(ww / 2 - 5, wh / 2, " No image. "); - else if(!image) + } + else if(!pixels) { char *buffer = malloc(ww + 1); snprintf(buffer, ww, " Error loading `%s'. ", list[current]); buffer[ww] = '\0'; + caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); caca_putstr((ww - strlen(buffer)) / 2, wh / 2, buffer); free(buffer); } @@ -247,112 +283,308 @@ int main(int argc, char **argv) int yn = h / (2 + zoom); if(x < xn) x = xn; if(y < yn) y = yn; - if(xn + x > w) x = w - xn; - if(yn + y > h) y = h - yn; - newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w, - 0x00ff0000, 0x0000ff00, 0x000000ff, - 0xff000000); + if(xn + x > (int)w) x = w - xn; + if(yn + y > (int)h) y = h - yn; + newbitmap = caca_create_bitmap(bpp, 2 * xn, 2 * yn, depth * w, + rmask, gmask, bmask, amask); + if(bpp == 8) + caca_set_bitmap_palette(newbitmap, red, green, blue, alpha); draw_checkers(0, fullscreen ? 0 : 1, - ww - 1, fullscreen ? wh - 1 : wh - 2); + ww - 1, fullscreen ? wh - 1 : wh - 3); caca_draw_bitmap(0, fullscreen ? 0 : 1, - ww - 1, fullscreen ? wh - 1 : wh - 2, + ww - 1, fullscreen ? wh - 1 : wh - 3, newbitmap, - pixels + 4 * (x - xn) + 4 * w * (y - yn)); + pixels + depth * (x - xn) + depth * w * (y - yn)); caca_free_bitmap(newbitmap); } else { draw_checkers(0, fullscreen ? 0 : 1, - ww - 1, fullscreen ? wh - 1 : wh - 2); + ww - 1, fullscreen ? wh - 1 : wh - 3); caca_draw_bitmap(0, fullscreen ? 0 : 1, - ww - 1, fullscreen ? wh - 1 : wh - 2, + ww - 1, fullscreen ? wh - 1 : wh - 3, bitmap, pixels); } - caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); - if(!fullscreen) { + caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); caca_draw_line(0, 0, ww - 1, 0, ' '); - caca_draw_line(0, wh - 1, ww - 1, wh - 1, '-'); + caca_draw_line(0, wh - 2, ww - 1, wh - 2, '-'); 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 (%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, + caca_printf(3, wh - 2, "cacaview %s", VERSION); + caca_printf(ww - 14, wh - 2, "(zoom: %s%i)", zoom > 0 ? "+" : "", zoom); + + caca_set_color(CACA_COLOR_LIGHTRED, CACA_COLOR_BLACK); + caca_draw_line(0, wh - 1, ww - 1, wh - 1, ' '); + switch(status) + { + case STATUS_ANTIALIASING: + caca_printf(0, wh - 1, "Antialiasing: %s", + caca_get_feature_name(caca_get_feature(CACA_ANTIALIASING))); + break; + case STATUS_DITHERING: + caca_printf(0, wh - 1, "Dithering: %s", + caca_get_feature_name(caca_get_feature(CACA_DITHERING))); + break; + case STATUS_BACKGROUND: + caca_printf(0, wh - 1, "Background: %s", + caca_get_feature_name(caca_get_feature(CACA_BACKGROUND))); + break; + } } 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, " 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; + caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); + caca_putstr(ww - 25, 2, " +: zoom in "); + caca_putstr(ww - 25, 3, " -: zoom out "); + caca_putstr(ww - 25, 4, " x: reset zoom "); + caca_putstr(ww - 25, 5, " ---------------------- "); + caca_putstr(ww - 25, 6, " hjkl: move view "); + caca_putstr(ww - 25, 7, " arrows: move view "); + caca_putstr(ww - 25, 8, " ---------------------- "); + caca_putstr(ww - 25, 9, " a: antialiasing method "); + caca_putstr(ww - 25, 10, " d: dithering method "); + caca_putstr(ww - 25, 11, " b: background mode "); + caca_putstr(ww - 25, 12, " ---------------------- "); + caca_putstr(ww - 25, 13, " ?: help "); + caca_putstr(ww - 25, 14, " q: quit "); } caca_refresh(); update = 0; } - if(bitmap) - caca_free_bitmap(bitmap); - if(image) - imlib_free_image(); - /* Clean up */ + unload_image(); caca_end(); return 0; } -static void load_image(const char *name) +static void unload_image(void) { - /* Empty previous data */ +#ifdef HAVE_IMLIB2_H if(image) imlib_free_image(); - + image = NULL; + pixels = NULL; +#else + if(pixels) + free(pixels); + pixels = NULL; +#endif if(bitmap) caca_free_bitmap(bitmap); - - image = NULL; bitmap = NULL; +} +static void load_image(const char *name) +{ +#ifdef HAVE_IMLIB2_H /* Load the new image */ image = imlib_load_image(name); if(!image) - { return; - } imlib_context_set_image(image); pixels = (char *)imlib_image_get_data_for_reading_only(); w = imlib_image_get_width(); h = imlib_image_get_height(); - x = w / 2; - y = h / 2; + rmask = 0x00ff0000; + gmask = 0x0000ff00; + bmask = 0x000000ff; + amask = 0xff000000; + bpp = 32; + depth = 4; /* Create the libcaca bitmap */ - bitmap = caca_create_bitmap(32, w, h, 4 * w, 0x00ff0000, 0x0000ff00, - 0x000000ff, 0xff000000); + bitmap = caca_create_bitmap(bpp, w, h, depth * w, + rmask, gmask, bmask, amask); if(!bitmap) { imlib_free_image(); image = NULL; } + +#else + /* Try to load a BMP file */ + FILE *fp; + unsigned int i, colors, offset, tmp, planes; + + fp = fopen(name, "rb"); + if(!fp) + return; + + if(freadshort(fp) != 0x4d42) + { + fclose(fp); + return; + } + + freadint(fp); /* size */ + freadshort(fp); /* reserved 1 */ + freadshort(fp); /* reserved 2 */ + + offset = freadint(fp); + + tmp = freadint(fp); /* header size */ + if(tmp == 40) + { + w = freadint(fp); + h = freadint(fp); + planes = freadshort(fp); + bpp = freadshort(fp); + + tmp = freadint(fp); /* compression */ + if(tmp != 0) + { + fclose(fp); + return; + } + + freadint(fp); /* sizeimage */ + freadint(fp); /* xpelspermeter */ + freadint(fp); /* ypelspermeter */ + freadint(fp); /* biclrused */ + freadint(fp); /* biclrimportantn */ + + colors = (offset - 54) / 4; + for(i = 0; i < colors && i < 256; i++) + { + blue[i] = freadchar(fp) * 16; + green[i] = freadchar(fp) * 16; + red[i] = freadchar(fp) * 16; + alpha[i] = 0; + freadchar(fp); + } + } + else if(tmp == 12) + { + w = freadint(fp); + h = freadint(fp); + planes = freadshort(fp); + bpp = freadshort(fp); + + colors = (offset - 26) / 3; + for(i = 0; i < colors && i < 256; i++) + { + blue[i] = freadchar(fp); + green[i] = freadchar(fp); + red[i] = freadchar(fp); + alpha[i] = 0; + } + } + else + { + fclose(fp); + return; + } + + /* Fill the rest of the palette */ + for(i = colors; i < 256; i++) + blue[i] = green[i] = red[i] = alpha[i] = 0; + + depth = (bpp + 7) / 8; + + /* Sanity check */ + if(!w || w > 0x10000 || !h || h > 0x10000 || planes != 1 /*|| bpp != 24*/) + { + fclose(fp); + return; + } + + /* Allocate the pixel buffer */ + pixels = malloc(w * h * depth); + if(!pixels) + { + fclose(fp); + return; + } + + memset(pixels, 0, w * h * depth); + + /* Read the bitmap data */ + for(i = h; i--; ) + { + unsigned int j, k, bits = 0; + + switch(bpp) + { + case 1: + for(j = 0; j < w; j++) + { + k = j % 32; + if(k == 0) + bits = freadint(fp); + pixels[w * i * depth + j] = + (bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0xf; + } + break; + case 4: + for(j = 0; j < w; j++) + { + k = j % 8; + if(k == 0) + bits = freadint(fp); + pixels[w * i * depth + j] = + (bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf; + } + break; + default: + fread(pixels + w * i * depth, w * depth, 1, fp); + /* Pad reads to 4 bytes */ + tmp = (4 - (w * depth) % 4) % 4; + while(tmp--) + freadchar(fp); + break; + } + } + + switch(depth) + { + case 3: + rmask = 0xff0000; + gmask = 0x00ff00; + bmask = 0x0000ff; + amask = 0x000000; + break; + case 2: /* XXX: those are the 16 bits values */ + rmask = 0x7c00; + gmask = 0x03e0; + bmask = 0x001f; + amask = 0x0000; + break; + case 1: + default: + bpp = 8; + rmask = gmask = bmask = amask = 0; + break; + } + + fclose(fp); + + /* Create the libcaca bitmap */ + bitmap = caca_create_bitmap(bpp, w, h, depth * w, + rmask, gmask, bmask, amask); + if(!bitmap) + { + free(pixels); + pixels = NULL; + return; + } + + if(bpp == 8) + caca_set_bitmap_palette(bitmap, red, green, blue, alpha); +#endif + + x = w / 2; + y = h / 2; } static void draw_checkers(unsigned int x1, unsigned int y1, @@ -363,7 +595,7 @@ static void draw_checkers(unsigned int x1, unsigned int y1, for(yn = y1; yn <= y2; yn++) for(xn = x1; xn <= x2; xn++) { - if(((xn / 4) ^ (yn / 2)) & 1) + if((((xn - x1) / 5) ^ ((yn - y1) / 3)) & 1) caca_set_color(CACA_COLOR_LIGHTGRAY, CACA_COLOR_DARKGRAY); else caca_set_color(CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY); @@ -371,3 +603,27 @@ static void draw_checkers(unsigned int x1, unsigned int y1, } } +#if !defined(HAVE_IMLIB2_H) +static int freadint(FILE *fp) +{ + unsigned char buffer[4]; + fread(buffer, 4, 1, fp); + return ((int)buffer[3] << 24) | ((int)buffer[2] << 16) + | ((int)buffer[1] << 8) | ((int)buffer[0]); +} + +static int freadshort(FILE *fp) +{ + unsigned char buffer[2]; + fread(buffer, 2, 1, fp); + return ((int)buffer[1] << 8) | ((int)buffer[0]); +} + +static int freadchar(FILE *fp) +{ + unsigned char buffer; + fread(&buffer, 1, 1, fp); + return (int)buffer; +} +#endif +