read.c (2160B)
1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 6 Memimage* 7 readmemimage(int fd) 8 { 9 char hdr[5*12+1]; 10 int dy; 11 u32int chan; 12 uint l, n; 13 int m, j; 14 int new, miny, maxy; 15 Rectangle r; 16 uchar *tmp; 17 int ldepth, chunk; 18 Memimage *i; 19 20 if(readn(fd, hdr, 11) != 11){ 21 werrstr("readimage: short header"); 22 return nil; 23 } 24 if(memcmp(hdr, "compressed\n", 11) == 0) 25 return creadmemimage(fd); 26 if(readn(fd, hdr+11, 5*12-11) != 5*12-11){ 27 werrstr("readimage: short header (2)"); 28 return nil; 29 } 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 i = allocmemimage(r, chan); 76 if(i == nil) 77 return nil; 78 chunk = 32*1024; 79 if(chunk < l) 80 chunk = l; 81 tmp = malloc(chunk); 82 if(tmp == nil) 83 goto Err; 84 while(maxy > miny){ 85 dy = maxy - miny; 86 if(dy*l > chunk) 87 dy = chunk/l; 88 if(dy <= 0){ 89 werrstr("readmemimage: image too wide for buffer"); 90 goto Err; 91 } 92 n = dy*l; 93 m = readn(fd, tmp, n); 94 if(m != n){ 95 werrstr("readmemimage: read count %d not %d: %r", m, n); 96 Err: 97 freememimage(i); 98 free(tmp); 99 return nil; 100 } 101 if(!new) /* an old image: must flip all the bits */ 102 for(j=0; j<chunk; j++) 103 tmp[j] ^= 0xFF; 104 105 if(loadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, chunk) <= 0) 106 goto Err; 107 miny += dy; 108 } 109 free(tmp); 110 return i; 111 }