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