readimage.c (2432B)
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 u32int 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 }