};
struct bmp_palette {
- uint8_t zero;
uint8_t blue;
uint8_t green;
uint8_t red;
+ uint8_t zero;
};
struct box {
int16_t *err_cur; /* ptr to current line's errors */
int16_t *err_next; /* ptr to next line's errors */
int dither=1; /* should we dither? */
+int rsize; /* bmp size of row in bytes */
#ifndef LITTLE_ENDIAN
uint16_t swizzle16( uint16_t d ){
}
#endif
-void println( uint8_t *buf){
- int i;
- for( i=0; i<42; i++){
- printf("%.2x ", buf[i] );
- }
- printf("\n");
-}
-
/* scan the tty driver's nodes. Pick the one that gives us the most resolution at 1bpp, and can do a direct WRITE ioctl */
int scan_modes(void) {
}
}
-void bpp32( uint16_t no ){
+void bpp32( int no ){
int i,j,k,c,x,e;
int erri=1;
uint8_t *out = obuf+sizeof(struct box);
for( i=0; i<32; i++){
c=0;
for( j=0; j<8; j++ ){
- /* fixme: the following color translation only
- works with big endian... add a ifdef for little */
- switch( no ){
- case 16:
- p.green = (*(in+1) << 1) & 0xf8;
- p.red = (*(in+1) << 6) | *in >> 5;
- p.blue = *in << 3 ;
- in += 2;
- break;
- case 32:
- in++;
- case 24:
- p.blue = *in++;
- p.green = *in++;
- p.red = *in++;
+ if( in < lbuf + rsize ){
+ /* fixme: the following color translation only
+ works with big endian... add a ifdef for little */
+ switch( no ){
+ case 16:
+ p.green = (*(in+1) << 1) & 0xf8;
+ p.red = (*(in+1) << 6) | *in >> 5;
+ p.blue = *in << 3 ;
+ in += 2;
+ break;
+ case 32:
+ in++;
+ case 24:
+ p.blue = *in++;
+ p.green = *in++;
+ p.red = *in++;
+ }
+ }
+ else{
+ p.green = 0;
+ p.red = 0 ;
+ p.blue = 0 ;
}
c = c << 1;
x= intensity( &p );
uint8_t pix[8];
flip_err();
+
memset( err_next, 0, 516 );
+
for( i=0; i<32; i++){
c=0;
for( j=0; j<no; j++ ){
- switch( no ){
- case 2:
- pix[0]= *in >> 6;
- pix[1]= *in >> 4 & 0x3;
- pix[2]= *in >> 2 & 0x3;
- pix[3]= *in++ & 0x3;
- break;
- case 4:
- pix[0]= *in >> 4;
- pix[1]= *in++ & 0xf;
- break;
- case 8:
- pix[0]= *in++;
- break;
- /* default case should be caught by caller */
+
+ if( in < lbuf + rsize ){
+ switch( no ){
+ case 1:
+ pix[0]= *in >> 7;
+ pix[1]= *in >> 6 & 1;
+ pix[2]= *in >> 5 & 1;
+ pix[3]= *in >> 4 & 1;
+ pix[4]= *in >> 3 & 1;
+ pix[5]= *in >> 2 & 1;
+ pix[6]= *in >> 1 & 1;
+ pix[7]= *in & 1;
+ in++;
+ break;
+ case 2:
+ pix[0]= *in >> 6;
+ pix[1]= *in >> 4 & 0x3;
+ pix[2]= *in >> 2 & 0x3;
+ pix[3]= *in++ & 0x3;
+ break;
+ case 4:
+ pix[0]= *in >> 4;
+ pix[1]= *in++ & 0xf;
+ break;
+ case 8:
+ pix[0]= *in++;
+ break;
+ }
}
- for( k=0; k<8/no; k ++ ){
+ else{
+ for( k=j; k<8/no; k++ ) pix[k]=0;
+ }
+
+ for( k=0; k<8/no; k++ ){
c = c << 1;
x= intensity( &(pal[ pix[k] ]) );
+
if( dither )
x += err_cur[ erri ]/16;
if( x > 127 ){
int fd,ret;
struct bmp_header h;
struct bmp_dib d;
- int rsize;
struct box *lbox;
int i,j;
+ int llb;
if( argc<2 )
exit_err_mess("usage: fview file");
if( ret != sizeof(struct bmp_palette)*d.colors )
exit_err_mess("read error loading palette");
+
/* Allocate dithering error buffers */
- /* fixme: need to check for malloc errors */
error1 = calloc( 256 + 2, sizeof( int16_t ) );
error2 = calloc( 256 + 2, sizeof( int16_t ) );
if( error1 == NULL | error2 == NULL )
exit_err_mess("cannot alloc dither buffers");
flip_err();
-
printf("header: %c%c\n", h.header[0], h.header[1] );
printf("width: %d, height: %d\n", (uint16_t)d.width, (uint16_t)d.height );
exit_err_mess("unsupported bmp format");
if( d.comp )
exit_err_mess("compression not supported");
-
-
+
/* alloc bmp line buffers */
rsize = (( d.bpp * d.width + 31 ) / 32 ) * 4;
if( lbuf == NULL )
exit_err_mess("cannot malloc line buffer");
- obuf=malloc( disp.width / 8 + sizeof(struct box) );
- if( obuf == NULL )
- exit_err_mess("cannot malloc dev buffer");
-
- lbox=(struct box *)obuf;
-
if( lseek( fd, h.offset, SEEK_SET)<0 )
exit_err_mess("seek error in bitmap file");
- lbox->size = 40;
- lbox->x = 0;
- lbox->h = 1;
- lbox->w = 32;
-
/* set video mode */
-
+
disp.mode=scan_modes();
if( disp.mode < 0 )
exit_err_mess("No suitable graphics mode found");
if( ioctl( 1, GFXIOC_SETMODE, &disp ) < 0 )
exit_err_mess("Cannot set graphics mode");
+ obuf=malloc( disp.width / 8 + sizeof(struct box) );
+ if( obuf == NULL )
+ exit_err_mess("cannot malloc dev buffer");
+
+ lbox=(struct box *)obuf;
+ lbox->size = disp.width / 8 + sizeof(struct box);
+ lbox->x = 0;
+ lbox->h = 1;
+ lbox->w = 32;
+
+
+ /* calc starting screen Y*/
+ if( d.height < disp.height )
+ llb = d.height-1;
+ else llb = disp.height-1;
+
+
/* loop */
for( i=disp.height-1; i>-1; i-- ){
- /* get a line from the file */
- ret=read( fd, lbuf, rsize );
- if( ret < rsize ) {
- printf("file read error: %d\n", ret );
- goto leave;
+ if( i <= llb ){
+ /* get a line from the file */
+ ret=read( fd, lbuf, rsize );
+
+ if( ret < rsize ) {
+ printf("file read error: %d\n", ret );
+ goto leave;
+ }
+
+ /* pixate the transels here */
+ switch( d.bpp ){
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ bpp( d.bpp );
+ break;
+ case 16:
+ case 24:
+ case 32:
+ bpp32( d.bpp );
+ break;
+ default:
+ printf("unsupported bpp.\n");
+ goto leave;
+ }
}
- /* pixate the transels here */
- switch( d.bpp ){
- case 1:
- /* fixme: fast, but doesn't do palette lookup :( */
- memcpy( obuf+sizeof(struct box), lbuf, 32 );
- break;
- case 2:
- case 4:
- case 8:
- bpp( d.bpp );
- break;
- case 16:
- case 24:
- case 32:
- bpp32( d.bpp );
- break;
- default:
- printf("unsupported bpp.\n");
- goto leave;
+ else{
+ memset( obuf+sizeof(struct box), 0, 32 );
}
/* output line to video device */
- lbox->y = i;
- ret=ioctl( 0, GFXIOC_WRITE, obuf );
+ lbox->y = i;
+ ret=ioctl( 0, GFXIOC_WRITE, obuf );
if( ret < 0 ){
printf("dev write error: %d\n", ret );
goto leave;