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