blob: bd72132acb210c63ccf071d977027196114f42da [file] [log] [blame]
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "sky.h"
static void dodecode(Biobuf*, Pix*, int, int, uchar*);
static int32 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
int32 getlong(uchar *p)
{
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}