1implement RImagefile; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 draw: Draw; 8 9include "bufio.m"; 10 bufio: Bufio; 11 Iobuf: import bufio; 12 13include "imagefile.m"; 14 15init(iomod: Bufio) 16{ 17 if(sys == nil) 18 sys = load Sys Sys->PATH; 19 bufio = iomod; 20} 21 22readmulti(fd: ref Iobuf): (array of ref Rawimage, string) 23{ 24 (i, err) := read(fd); 25 if(i != nil){ 26 a := array[1] of { i }; 27 return (a, err); 28 } 29 return (nil, err); 30} 31 32read(fd: ref Iobuf): (ref Rawimage, string) 33{ 34 width, height, fnd: int; 35 (fnd, width) = get_define(fd); 36 if(fnd) 37 (fnd, height) = get_define(fd); 38 if(!fnd) 39 return (nil, "xbitmap doesn't start with width and height"); 40 if(height <= 0 || width <= 0) 41 return (nil, "xbitmap has bad width or height"); 42 # now, optional x_hot, y_hot 43 (fnd, nil) = get_define(fd); 44 if(fnd) 45 (fnd, nil) = get_define(fd); 46 # now expect 'static char x...x_bits[] = {' 47 if(!get_to_char(fd, '{')) 48 return (nil, "xbitmap premature eof"); 49 50 bytesperline := (width+7) / 8; 51 pixels := array[width*height] of byte; 52 pixi := 0; 53 for(i := 0; i < height; i++) { 54 for(j := 0; j < bytesperline; j++) { 55 (vfnd, v) := get_hexbyte(fd); 56 if(!vfnd) 57 return (nil, "xbitmap premature eof"); 58 kend := 7; 59 if(j == bytesperline-1) 60 kend = (width-1)%8; 61 for(k := 0; k <= kend; k++) { 62 if(v & (1<<k)) 63 pixels[pixi] = byte 0; 64 else 65 pixels[pixi] = byte 1; 66 pixi++; 67 } 68 } 69 } 70 cmap := array[6] of {byte 0, byte 0, byte 0, 71 byte 255, byte 255, byte 255}; 72 chans := array[1] of {pixels}; 73 ans := ref Rawimage(Draw->Rect((0,0),(width,height)), cmap, 0, byte 0, 1, chans, CRGB1, 0); 74 return (ans, ""); 75} 76 77# get a line, which should be of form 78# '#define fieldname val' 79# and return (found, integer rep of val) 80get_define(fd: ref Iobuf) : (int, int) 81{ 82 c := fd.getc(); 83 if(c != '#') { 84 fd.ungetc(); 85 return (0, 0); 86 } 87 line := fd.gets('\n'); 88 for(i := len line -1; i >= 0; i--) 89 if(line[i] == ' ') 90 break; 91 val := int line[i+1:]; 92 return (1, val); 93} 94 95# read fd until get char cterm; return 1 if found 96get_to_char(fd: ref Iobuf, cterm: int) : int 97{ 98 for(;;) { 99 c := fd.getc(); 100 if(c < 0) 101 return c; 102 if(c == cterm) 103 return 1; 104 } 105} 106 107# read fd until get xDD, were DD are hex digits. 108# return (found, value of DD as integer) 109get_hexbyte(fd: ref Iobuf) : (int, int) 110{ 111 if(!get_to_char(fd, 'x')) 112 return (0, 0); 113 n1 := hexdig(fd.getc()); 114 n2 := hexdig(fd.getc()); 115 if(n1 < 0 || n2 < 0) 116 return (0, 0); 117 return (1, (n1<<4) | n2); 118} 119 120hexdig(c: int) : int 121{ 122 if('0' <= c && c <= '9') 123 c -= '0'; 124 else if('a' <= c && c <= 'f') 125 c += 10 - 'a'; 126 else if('A' <= c && c <= 'F') 127 c += 10 - 'A'; 128 else 129 c = -1; 130 return c; 131} 132