1 #include "../lib9.h" 2 3 #include "../libdraw/draw.h" 4 #include "../libmemdraw/memdraw.h" 5 6 /* 7 * compressed data are sequences of byte codes. 8 * if the first byte b has the 0x80 bit set, the next (b^0x80)+1 bytes 9 * are data. otherwise, it's two bytes specifying a previous string to repeat. 10 */ 11 static void 12 twiddlecompressed(uchar *buf, int n) 13 { 14 uchar *ebuf; 15 int j, k, c; 16 17 ebuf = buf+n; 18 while(buf < ebuf){ 19 c = *buf++; 20 if(c >= 128){ 21 k = c-128+1; 22 for(j=0; j<k; j++, buf++) 23 *buf ^= 0xFF; 24 }else 25 buf++; 26 } 27 } 28 29 Memimage* 30 creadmemimage(int fd) 31 { 32 char hdr[5*12+1]; 33 Rectangle r; 34 int m, nb, miny, maxy, new, ldepth; 35 uchar *buf; 36 Memimage *i; 37 ulong chan; 38 39 if(readn(fd, hdr, 5*12) != 5*12) 40 return nil; 41 42 /* 43 * distinguish new channel descriptor from old ldepth. 44 * channel descriptors have letters as well as numbers, 45 * while ldepths are a single digit formatted as %-11d. 46 */ 47 new = 0; 48 for(m=0; m<10; m++){ 49 if(hdr[m] != ' '){ 50 new = 1; 51 break; 52 } 53 } 54 if(hdr[11] != ' '){ 55 werrstr("creadimage: bad format"); 56 return nil; 57 } 58 if(new){ 59 hdr[11] = '\0'; 60 if((chan = strtochan(hdr)) == 0){ 61 werrstr("creadimage: bad channel string %s", hdr); 62 return nil; 63 } 64 }else{ 65 ldepth = ((int)hdr[10])-'0'; 66 if(ldepth<0 || ldepth>3){ 67 werrstr("creadimage: bad ldepth %d", ldepth); 68 return nil; 69 } 70 chan = drawld2chan[ldepth]; 71 } 72 r.min.x=atoi(hdr+1*12); 73 r.min.y=atoi(hdr+2*12); 74 r.max.x=atoi(hdr+3*12); 75 r.max.y=atoi(hdr+4*12); 76 if(r.min.x>r.max.x || r.min.y>r.max.y){ 77 werrstr("creadimage: bad rectangle"); 78 return nil; 79 } 80 81 i = allocmemimage(r, chan); 82 if(i == nil) 83 return nil; 84 buf = malloc(NCBLOCK); 85 if(buf == nil) 86 goto Errout; 87 miny = r.min.y; 88 while(miny != r.max.y){ 89 if(readn(fd, hdr, 2*12) != 2*12){ 90 Errout: 91 freememimage(i); 92 free(buf); 93 return nil; 94 } 95 maxy = atoi(hdr+0*12); 96 nb = atoi(hdr+1*12); 97 if(maxy<=miny || r.max.y<maxy){ 98 werrstr("readimage: bad maxy %d", maxy); 99 goto Errout; 100 } 101 if(nb<=0 || NCBLOCK<nb){ 102 werrstr("readimage: bad count %d", nb); 103 goto Errout; 104 } 105 if(readn(fd, buf, nb)!=nb) 106 goto Errout; 107 if(!new) /* old image: flip the data bits */ 108 twiddlecompressed(buf, nb); 109 cloadmemimage(i, Rect(r.min.x, miny, r.max.x, maxy), buf, nb); 110 miny = maxy; 111 } 112 free(buf); 113 return i; 114 } 115