Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
 
5
Image*
6
readimage(Display *d, int fd, int dolock)
7
{
8
	char hdr[5*12+1];
9
	int dy;
10
	int new;
11
	uint l, n;
12
	int m, j, chunk;
13
	int miny, maxy;
14
	Rectangle r;
15
	int ldepth;
16
	ulong chan;
17
	uchar *tmp;
18
	Image *i;
19
 
20
	if(readn(fd, hdr, 11) != 11)
21
		return nil;
22
	if(memcmp(hdr, "compressed\n", 11) == 0)
23
		return creadimage(d, fd, dolock);
24
	if(readn(fd, hdr+11, 5*12-11) != 5*12-11)
25
		return nil;
26
	if(d)
27
		chunk = d->bufsize - 32;	/* a little room for header */
28
	else
29
		chunk = 8192;
30
 
31
	/*
32
	 * distinguish new channel descriptor from old ldepth.
33
	 * channel descriptors have letters as well as numbers,
34
	 * while ldepths are a single digit formatted as %-11d.
35
	 */
36
	new = 0;
37
	for(m=0; m<10; m++){
38
		if(hdr[m] != ' '){
39
			new = 1;
40
			break;
41
		}
42
	}
43
	if(hdr[11] != ' '){
44
		werrstr("readimage: bad format");
45
		return nil;
46
	}
47
	if(new){
48
		hdr[11] = '\0';
49
		if((chan = strtochan(hdr)) == 0){
50
			werrstr("readimage: bad channel string %s", hdr);
51
			return nil;
52
		}
53
	}else{
54
		ldepth = ((int)hdr[10])-'0';
55
		if(ldepth<0 || ldepth>3){
56
			werrstr("readimage: bad ldepth %d", ldepth);
57
			return nil;
58
		}
59
		chan = drawld2chan[ldepth];
60
	}
61
 
62
	r.min.x = atoi(hdr+1*12);
63
	r.min.y = atoi(hdr+2*12);
64
	r.max.x = atoi(hdr+3*12);
65
	r.max.y = atoi(hdr+4*12);
66
	if(r.min.x>r.max.x || r.min.y>r.max.y){
67
		werrstr("readimage: bad rectangle");
68
		return nil;
69
	}
70
 
71
	miny = r.min.y;
72
	maxy = r.max.y;
73
 
74
	l = bytesperline(r, chantodepth(chan));
75
	if(d){
76
		if(dolock)
77
			lockdisplay(d);
78
		i = allocimage(d, r, chan, 0, -1);
79
		if(dolock)
80
			unlockdisplay(d);
81
		if(i == nil)
82
			return nil;
83
	}else{
84
		i = mallocz(sizeof(Image), 1);
85
		if(i == nil)
86
			return nil;
87
	}
88
 
89
	tmp = malloc(chunk);
90
	if(tmp == nil)
91
		goto Err;
92
	while(maxy > miny){
93
		dy = maxy - miny;
94
		if(dy*l > chunk)
95
			dy = chunk/l;
96
		if(dy <= 0){
97
			werrstr("readimage: image too wide for buffer");
98
			goto Err;
99
		}
100
		n = dy*l;
101
		m = readn(fd, tmp, n);
102
		if(m != n){
103
			werrstr("readimage: read count %d not %d: %r", m, n);
104
   Err:
105
			if(dolock)
106
				lockdisplay(d);
107
   Err1:
108
 			freeimage(i);
109
			if(dolock)
110
				unlockdisplay(d);
111
			free(tmp);
112
			return nil;
113
		}
114
		if(!new)	/* an old image: must flip all the bits */
115
			for(j=0; j<chunk; j++)
116
				tmp[j] ^= 0xFF;
117
 
118
		if(d){
119
			if(dolock)
120
				lockdisplay(d);
121
			if(loadimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, chunk) <= 0)
122
				goto Err1;
123
			if(dolock)
124
				unlockdisplay(d);
125
		}
126
		miny += dy;
127
	}
128
	free(tmp);
129
	return i;
130
}