1 #include "../lib9.h" 2 3 #include "../libdraw/draw.h" 4 #include "../libmemdraw/memdraw.h" 5 6 #define CHUNK 8000 7 8 Memimage* 9 readmemimage(int fd) 10 { 11 char hdr[5*12+1]; 12 int dy; 13 ulong chan; 14 uint l, m, n; 15 int j; 16 int new, miny, maxy; 17 Rectangle r; 18 uchar *tmp; 19 int ldepth; 20 Memimage *i; 21 22 if(readn(fd, hdr, 11) != 11) 23 return nil; 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 return nil; 28 29 /* 30 * distinguish new channel descriptor from old ldepth. 31 * channel descriptors have letters as well as numbers, 32 * while ldepths are a single digit formatted as %-11d. 33 */ 34 new = 0; 35 for(m=0; m<10; m++){ 36 if(hdr[m] != ' '){ 37 new = 1; 38 break; 39 } 40 } 41 if(hdr[11] != ' '){ 42 werrstr("readimage: bad format"); 43 return nil; 44 } 45 if(new){ 46 hdr[11] = '\0'; 47 if((chan = strtochan(hdr)) == 0){ 48 werrstr("readimage: bad channel string %s", hdr); 49 return nil; 50 } 51 }else{ 52 ldepth = ((int)hdr[10])-'0'; 53 if(ldepth<0 || ldepth>3){ 54 werrstr("readimage: bad ldepth %d", ldepth); 55 return nil; 56 } 57 chan = drawld2chan[ldepth]; 58 } 59 60 r.min.x = atoi(hdr+1*12); 61 r.min.y = atoi(hdr+2*12); 62 r.max.x = atoi(hdr+3*12); 63 r.max.y = atoi(hdr+4*12); 64 if(r.min.x>r.max.x || r.min.y>r.max.y){ 65 werrstr("readimage: bad rectangle"); 66 return nil; 67 } 68 69 miny = r.min.y; 70 maxy = r.max.y; 71 72 l = bytesperline(r, chantodepth(chan)); 73 i = allocmemimage(r, chan); 74 if(i == nil) 75 return nil; 76 tmp = malloc(CHUNK); 77 if(tmp == nil) 78 goto Err; 79 while(maxy > miny){ 80 dy = maxy - miny; 81 if(dy*l > CHUNK) 82 dy = CHUNK/l; 83 if(dy <= 0){ 84 werrstr("readmemimage: image too wide for buffer"); 85 goto Err; 86 } 87 n = dy*l; 88 m = readn(fd, tmp, n); 89 if(m != n){ 90 werrstr("readmemimage: read count %d not %d: %r", m, n); 91 Err: 92 freememimage(i); 93 free(tmp); 94 return nil; 95 } 96 if(!new) /* an old image: must flip all the bits */ 97 for(j=0; j<CHUNK; j++) 98 tmp[j] ^= 0xFF; 99 100 if(loadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), tmp, CHUNK) <= 0) 101 goto Err; 102 miny += dy; 103 } 104 free(tmp); 105 return i; 106 } 107