xref: /plan9/sys/src/cmd/scat/dssread.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1 #include	<u.h>
2 #include	<libc.h>
3 #include	<bio.h>
4 #include	"sky.h"
5 
6 static	void	dodecode(Biobuf*, Pix*, int, int, uchar*);
7 static	long	getlong(uchar*);
8 int	debug;
9 
10 Img*
dssread(char * file)11 dssread(char *file)
12 {
13 	int nx, ny, scale, sumall;
14 	Pix  *p, *pend;
15 	uchar buf[21];
16 	Biobuf *bp;
17 	Img *ip;
18 
19 	if(debug)
20 		Bprint(&bout, "reading %s\n", file);
21 	bp = Bopen(file, OREAD);
22 	if(bp == 0)
23 		return 0;
24 	if(Bread(bp, buf, sizeof(buf)) != sizeof(buf) ||
25 	   buf[0] != 0xdd || buf[1] != 0x99){
26 		werrstr("bad format");
27 		return 0;
28 	}
29 	nx = getlong(buf+2);
30 	ny = getlong(buf+6);
31 	scale = getlong(buf+10);
32 	sumall = getlong(buf+14);
33 	if(debug)
34 		fprint(2, "%s: nx=%d, ny=%d, scale=%d, sumall=%d, nbitplanes=%d,%d,%d\n",
35 			file, nx, ny, scale, sumall, buf[18], buf[19], buf[20]);
36 	ip = malloc(sizeof(Img) + (nx*ny-1)*sizeof(int));
37 	if(ip == 0){
38 		Bterm(bp);
39 		werrstr("no memory");
40 		return 0;
41 	}
42 	ip->nx = nx;
43 	ip->ny = ny;
44 	dodecode(bp, ip->a, nx, ny, buf+18);
45 	ip->a[0] = sumall;	/* sum of all pixels */
46 	Bterm(bp);
47 	if(scale > 1){
48 		p = ip->a;
49 		pend = &ip->a[nx*ny];
50 		while(p < pend)
51 			*p++ *= scale;
52 	}
53 	hinv(ip->a, nx, ny);
54 	return ip;
55 }
56 
57 static
58 void
dodecode(Biobuf * infile,Pix * a,int nx,int ny,uchar * nbitplanes)59 dodecode(Biobuf *infile, Pix  *a, int nx, int ny, uchar *nbitplanes)
60 {
61 	int nel, nx2, ny2, bits, mask;
62 	Pix *aend, px;
63 
64 	nel = nx*ny;
65 	nx2 = (nx+1)/2;
66 	ny2 = (ny+1)/2;
67 	memset(a, 0, nel*sizeof(*a));
68 
69 	/*
70 	 * Initialize bit input
71 	 */
72 	start_inputing_bits();
73 
74 	/*
75 	 * read bit planes for each quadrant
76 	 */
77 	qtree_decode(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
78 	qtree_decode(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
79 	qtree_decode(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
80 	qtree_decode(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
81 
82 	/*
83 	 * make sure there is an EOF symbol (nybble=0) at end
84 	 */
85 	if(input_nybble(infile) != 0){
86 		fprint(2, "dodecode: bad bit plane values\n");
87 		exits("format");
88 	}
89 
90 	/*
91 	 * get the sign bits
92 	 */
93 	aend = &a[nel];
94 	mask = 0;
95 	bits = 0;;
96 	for(; a<aend; a++) {
97 		if(px = *a) {
98 			if(mask == 0) {
99 				mask = 0x80;
100 				bits = Bgetc(infile);
101 			}
102 			if(mask & bits)
103 				*a = -px;
104 			mask >>= 1;
105 		}
106 	}
107 }
108 
109 static
getlong(uchar * p)110 long	getlong(uchar *p)
111 {
112 	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
113 }
114