>>33909
fixed a bunch of stuff, its doing outlines right now and its more usable, dont know if c++ has a better way of doing bit manipulation since it makes the code a mess
[code]#include <iostream>
#include <wchar.h>
#include <locale>
#include <stdlib.h>
using namespace std;
struct bitmap
{
int w, h;
unsigned char *bits; // changed to actual bitmap, read using bitmasks
};
class framebuffer
{
public:
unsigned int width;
unsigned int height;
wchar_t *buffer;
int dotn[8] = { 0, 3, 1, 4, 2, 5, 6, 7 };
void init( unsigned int xmax, unsigned int ymax )
{
width = xmax;
height = ymax;
buffer = (wchar_t*) malloc( width * height * sizeof(wchar_t) );
}
void clear( void )
{
wmemset( buffer, 0x2800, width * height );
}
void draw( void )
{
for ( int r=0; r < height; r++ )
wprintf( L"%*.*ls\n", width,width, &buffer[ r*width ] );
}
void putpixel( unsigned int x, unsigned int y )
{
int posx = x/2;
int posy = y/4;
x %= 2;
y %= 4;
if ( posx > width || posy > height ) // out of bounds
return;
wchar_t pixel = buffer[ posy * width + posx ];
pixel -= 0x2800;
if ( pixel & ( 1 << dotn[ y*2 + x ] ) ) // already set
return;
pixel |= 1 << dotn[ y*2 + x ];
pixel += 0x2800;
buffer[ posy * width + posx ] = pixel;
}
void putbitmap( int x, int y, struct bitmap *bmp )
{
for ( int yc=0; yc < bmp->h; yc++ )
for ( int xc=0; xc < bmp->w/8; xc++ )
for ( int bit=0; bit < 8; bit++ )
if ( bmp->bits[ yc * (bmp->w/8) + xc ] & (1<<bit) )
putpixel( x + xc*8 + bit, y + yc );
}
} FB;
struct bitmap *loadfile( const char *filename, unsigned char brightness, unsigned char contrast, int invert )
{
FILE *fp = fopen( filename, "r" );
if ( !fp )
wcout << L"! ERROR couldnt open " << filename << L'\n', exit(1);
struct Header
{
unsigned int size;
unsigned int x;
unsigned int y;
unsigned short int planec;
unsigned short int depth;
unsigned int compression;
unsigned int rez;
unsigned int xbitc;
unsigned int ybitc;
unsigned int biClrUsed;
unsigned int biClrImportant;
}
attribute ((packed)) Header;
fseek( fp, 14, SEEK_SET );
fread( (char*)&Header.size, 1, sizeof( struct Header ), fp );
fseek( fp, 32*4, SEEK_SET ); // XXX misalignment since my header def is wrong or something
if ( Header.depth != 32 )
wcout << L"! ERROR file must be a 32bit .bmp\n" << (wchar_t)0x1F620, exit(2);
struct bitmap *bmp = (struct bitmap*) malloc( sizeof(struct bitmap) );
// resize to framebuffer
float xscale = ( Header.x > (FB.width *2) ) ? (float)Header.x / (float)(FB.width*2) : 1;
float yscale = ( Header.y > (FB.height *4) ) ? (float)Header.y / (float)(FB.height*4) : 1;
bmp->w = (float)Header.x / xscale;
bmp->h = (float)Header.y / yscale;
bmp->bits = (unsigned char*) malloc( (bmp->h) * (1 + bmp->w/8) );
char *file = (char*) malloc( Header.x * Header.y * 32 );
fread( file, 1, Header.x * Header.y * 32, fp );
int32_t prev = 0;
int x=0, y=0;
for ( float r=Header.y -1; r >= 0; r -= yscale, y++, x=0 )
for ( float c=0; c < Header.x; c += xscale, x++ )
{
int check = 0;
// check pixel for brightness
int32_t pixel = ((int32_t*)file)[ (int)r * Header.x + (int)c ];
unsigned char cur = 0;
cur |= ( pixel & (0xff) );
cur |= ( pixel & (0xff<<8) );
cur |= ( pixel & (0xff<<16) );
check = ( cur < brightness );
check ^= invert;
// check surounding pixels for contrast
unsigned int check2 = 0;
for ( int yd=-3; yd<4; yd++ ) // TODO test size should be based on resolution
for ( int xd=-3; xd<4; xd++ )
{
int y = (int)r + yd;
int x = (int)c + xd;
if
( ( !yd && !xd ) || // same pixel
( y < 0 || y >= Header.y ) || // out of bounds
( x < 0 || x >= Header.x ) // out of bounds
) continue;
int32_t pixel = ((int32_t*)file)[ y * Header.x + x ];
unsigned char near = 0;
near |= ( pixel & (0xff) );
near |= ( pixel & (0xff<<8) );
near |= ( pixel & (0xff<<16) );
if ( near > cur )
check2 += ( (near - cur) > contrast );
else
check2 += ( (cur - near) > contrast );
}
if ( check2 >= 16 ) // invert if in a cluster else outline
check = 0;
else
check |= check2;
int bit = x % 8;
if ( !bit )
bmp->bits[ y *( bmp->w/8 ) + x/8 ] = 0;
if ( check )
bmp->bits[ y *( bmp->w/8) + x/8 ] |= (1 << bit);
}
free( file );
fclose( fp );
return bmp;
}
int main( int argc, char **args )
{
if ( argc < 2 ) exit(1);
setlocale(LC_CTYPE, "");
// defaults
unsigned int xmax = 40; // terminal width
unsigned int ymax = 20; // terminal height
unsigned int brightness = 30; // shading level
unsigned int contrast = 20; // contour level
unsigned int xrez = xmax * 2; // pixel resolution
unsigned int yrez = ymax * 4; // pixel resolution
int invert = 0;
char *file;
for ( int i=1; i<argc; i++ )
{
char *arg = *(++args);
if ( *arg == '-' )
switch ( *(++arg) )
{
case 'r': // set resolution in pixels
args++; i++;
sscanf( *(args), "%dx%d", &xrez, &yrez );
xmax = xrez / 2;
ymax = yrez / 4;
break;
case 's': // set resolution in chars
args++; i++;
sscanf( *(args), "%dx%d", &xmax, &ymax );
xrez = xmax * 2;
yrez = ymax * 4;
break;
case 'b': // set brightness level
args++; i++;
sscanf( *(args), "%d", &brightness );
break;
case 'c': // et contrast level
args++; i++;
sscanf( *(args), "%iu", &contrast );
break;
case 'i': // invert shading
invert = 1;
break;
}
else
file = arg;
}
FB.init( xmax, ymax );
struct bitmap *pic = loadfile( file, brightness, contrast, invert );
if ( pic )
{
FB.clear();
wprintf( L"res: %dx%d\nsize: %dx%d\nb=%d c=%d\n",
xrez, yrez, xmax, ymax, brightness, contrast );
FB.putbitmap( 0, 0, pic );
FB.draw();
}
return