proper (slow) 1bpp mode + boarders + horrible buffer alloc.
authorBrett Gordon <beretta42@gmail.com>
Tue, 5 Jul 2016 15:15:00 +0000 (11:15 -0400)
committerBrett Gordon <beretta42@gmail.com>
Thu, 18 Aug 2016 17:33:24 +0000 (13:33 -0400)
Applications/fview/fview.c

index e94d618..a022103 100644 (file)
@@ -28,10 +28,10 @@ struct bmp_dib {
 };
 
 struct bmp_palette {
-       uint8_t zero;
        uint8_t blue;
        uint8_t green;
        uint8_t red;
+       uint8_t zero;
 };
 
 struct box {
@@ -52,6 +52,7 @@ int16_t *error2;            /* error buffer 2 */
 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 ){
@@ -67,14 +68,6 @@ uint32_t swizzle32( uint32_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) {
@@ -140,7 +133,7 @@ void fs_dist( int16_t e, uint16_t i ){
        }
 }       
 
-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);
@@ -153,21 +146,28 @@ void bpp32( uint16_t no ){
        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 );
@@ -198,29 +198,49 @@ void bpp( int no ){
        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 ){
@@ -245,9 +265,9 @@ int main( int argc, char *argv[] )
        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");
@@ -298,14 +318,13 @@ int main( int argc, char *argv[] )
        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 );
@@ -319,8 +338,7 @@ int main( int argc, char *argv[] )
                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;
 
@@ -328,23 +346,12 @@ int main( int argc, char *argv[] )
        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");
@@ -352,38 +359,59 @@ int main( int argc, char *argv[] )
        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;