xref: /inferno-os/libdraw/creadimage.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "lib9.h"
2 #include "draw.h"
3 #include "kernel.h"
4 
5 Image *
creadimage(Display * d,int fd,int dolock)6 creadimage(Display *d, int fd, int dolock)
7 {
8 	char hdr[5*12+1];
9 	Rectangle r;
10 	int m, nb, miny, maxy, new, ldepth, ncblock;
11 	uchar *buf, *a;
12 	Image *i;
13 	ulong chan;
14 	int font;
15 
16 	font = dolock&2;
17 	dolock &= 1;
18 	if(libreadn(fd, hdr, 5*12) != 5*12)
19 		return nil;
20 
21 	/*
22 	 * distinguish new channel descriptor from old ldepth.
23 	 * channel descriptors have letters as well as numbers,
24 	 * while ldepths are a single digit formatted as %-11d.
25 	 */
26 	new = 0;
27 	for(m=0; m<10; m++){
28 		if(hdr[m] != ' '){
29 			new = 1;
30 			break;
31 		}
32 	}
33 	if(hdr[11] != ' '){
34 		kwerrstr("creadimage: bad format");
35 		return nil;
36 	}
37 	if(new){
38 		hdr[11] = '\0';
39 		if((chan = strtochan(hdr)) == 0){
40 			kwerrstr("creadimage: bad channel string %s", hdr);
41 			return nil;
42 		}
43 	}else{
44 		ldepth = ((int)hdr[10])-'0';
45 		if(ldepth<0 || ldepth>3){
46 			kwerrstr("creadimage: bad ldepth %d", ldepth);
47 			return nil;
48 		}
49 		chan = drawld2chan[ldepth];
50 	}
51 	r.min.x=atoi(hdr+1*12);
52 	r.min.y=atoi(hdr+2*12);
53 	r.max.x=atoi(hdr+3*12);
54 	r.max.y=atoi(hdr+4*12);
55 	if(r.min.x>r.max.x || r.min.y>r.max.y){
56 		kwerrstr("creadimage: bad rectangle");
57 		return nil;
58 	}
59 
60 	if(dolock)
61 		dolock = lockdisplay(d);
62 	i = allocimage(d, r, chan, 0, 0);
63 	if(dolock)
64 		unlockdisplay(d);
65 	if(i == nil)
66 		return nil;
67 	ncblock = _compblocksize(r, i->depth);
68 	buf = malloc(ncblock);
69 	if(buf == nil)
70 		goto Errout;
71 	miny = r.min.y;
72 	while(miny != r.max.y){
73 		if(libreadn(fd, hdr, 2*12) != 2*12){
74 		Errout:
75 			if(dolock)
76 				lockdisplay(d);
77 		Erroutlock:
78 			freeimage(i);
79 			if(dolock)
80 				unlockdisplay(d);
81 			free(buf);
82 			return nil;
83 		}
84 		maxy = atoi(hdr+0*12);
85 		nb = atoi(hdr+1*12);
86 		if(maxy<=miny || r.max.y<maxy){
87 			kwerrstr("creadimage: bad maxy %d", maxy);
88 			goto Errout;
89 		}
90 		if(nb<=0 || ncblock<nb){
91 			kwerrstr("creadimage: bad count %d", nb);
92 			goto Errout;
93 		}
94 		if(libreadn(fd, buf, nb)!=nb)
95 			goto Errout;
96 		if(dolock)
97 			lockdisplay(d);
98 		a = bufimage(i->display, 21+nb);
99 		if(a == nil)
100 			goto Erroutlock;
101 		a[0] = 'Y';
102 		BPLONG(a+1, i->id);
103 		BPLONG(a+5, r.min.x);
104 		BPLONG(a+9, miny);
105 		BPLONG(a+13, r.max.x);
106 		BPLONG(a+17, maxy);
107 		if(!font&&!new)	/* old image: flip the data bits */
108 			_twiddlecompressed(buf, nb);
109 		memmove(a+21, buf, nb);
110 		if(dolock)
111 			unlockdisplay(d);
112 		miny = maxy;
113 	}
114 	free(buf);
115 	return i;
116 }
117