Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include        <u.h>
#include        <libc.h>
#include        <bio.h>
#include        "sky.h"

static  void    dodecode(Biobuf*, Pix*, int, int, uchar*);
static  long    getlong(uchar*);
int     debug;

Img*
dssread(char *file)
{
        int nx, ny, scale, sumall;
        Pix  *p, *pend;
        uchar buf[21];
        Biobuf *bp;
        Img *ip;

        if(debug)
                Bprint(&bout, "reading %s\n", file);
        bp = Bopen(file, OREAD);
        if(bp == 0)
                return 0;
        if(Bread(bp, buf, sizeof(buf)) != sizeof(buf) ||
           buf[0] != 0xdd || buf[1] != 0x99){
                werrstr("bad format");
                return 0;
        }
        nx = getlong(buf+2);
        ny = getlong(buf+6);
        scale = getlong(buf+10);
        sumall = getlong(buf+14);
        if(debug)
                fprint(2, "%s: nx=%d, ny=%d, scale=%d, sumall=%d, nbitplanes=%d,%d,%d\n",
                        file, nx, ny, scale, sumall, buf[18], buf[19], buf[20]);
        ip = malloc(sizeof(Img) + (nx*ny-1)*sizeof(int));
        if(ip == 0){
                Bterm(bp);
                werrstr("no memory");
                return 0;
        }
        ip->nx = nx;
        ip->ny = ny;
        dodecode(bp, ip->a, nx, ny, buf+18);
        ip->a[0] = sumall;      /* sum of all pixels */
        Bterm(bp);
        if(scale > 1){
                p = ip->a;
                pend = &ip->a[nx*ny];
                while(p < pend)
                        *p++ *= scale;
        }
        hinv(ip->a, nx, ny);
        return ip;
}

static
void
dodecode(Biobuf *infile, Pix  *a, int nx, int ny, uchar *nbitplanes)
{
        int nel, nx2, ny2, bits, mask;
        Pix *aend, px;

        nel = nx*ny;
        nx2 = (nx+1)/2;
        ny2 = (ny+1)/2;
        memset(a, 0, nel*sizeof(*a));

        /*
         * Initialize bit input
         */
        start_inputing_bits();

        /*
         * read bit planes for each quadrant
         */
        qtree_decode(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
        qtree_decode(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
        qtree_decode(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
        qtree_decode(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);

        /*
         * make sure there is an EOF symbol (nybble=0) at end
         */
        if(input_nybble(infile) != 0){
                fprint(2, "dodecode: bad bit plane values\n");
                exits("format");
        }

        /*
         * get the sign bits
         */
        aend = &a[nel];
        mask = 0;
        bits = 0;;
        for(; a<aend; a++) {
                if(px = *a) {
                        if(mask == 0) {
                                mask = 0x80;
                                bits = Bgetc(infile);
                        }
                        if(mask & bits)
                                *a = -px;
                        mask >>= 1;
                }
        }
}

static
long    getlong(uchar *p)
{
        return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}