@@ -28,24 +28,44 @@
#include <malloc.h>
#include <unistd.h>
#include <Imlib2.h>
#if defined(HAVE_IMLIB2_H)
# include <Imlib2.h>
#else
# include <stdio.h>
#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