9fans.net/go@v0.0.5/draw/memdraw/read.go (about) 1 package memdraw 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 8 "9fans.net/go/draw" 9 ) 10 11 func readmemimage(fd *os.File) (*Image, error) { 12 var hdr [5*12 + 1]byte 13 if _, err := io.ReadFull(fd, hdr[:11]); err != nil { 14 return nil, fmt.Errorf("readimage: %v", err) 15 } 16 if string(hdr[:11]) == "compressed\n" { 17 return creadmemimage(fd) 18 } 19 if _, err := io.ReadFull(fd, hdr[11:5*12]); err != nil { 20 return nil, fmt.Errorf("readimage: %v", err) 21 } 22 23 /* 24 * distinguish new channel descriptor from old ldepth. 25 * channel descriptors have letters as well as numbers, 26 * while ldepths are a single digit formatted as %-11d. 27 */ 28 new := false 29 var m int 30 for m = 0; m < 10; m++ { 31 if hdr[m] != ' ' { 32 new = true 33 break 34 } 35 } 36 if hdr[11] != ' ' { 37 return nil, fmt.Errorf("readimage: bad format") 38 } 39 var chan_ draw.Pix 40 if new { 41 s := string(hdr[:11]) 42 var err error 43 chan_, err = draw.ParsePix(s) 44 if err != nil { 45 return nil, fmt.Errorf("readimage: %v", err) 46 } 47 } else { 48 ldepth := (int(hdr[10])) - '0' 49 if ldepth < 0 || ldepth > 3 { 50 return nil, fmt.Errorf("readimage: bad ldepth %d", ldepth) 51 } 52 chan_ = ldepthToPix[ldepth] 53 } 54 var r draw.Rectangle 55 56 r.Min.X = atoi(hdr[1*12 : 2*12]) 57 r.Min.Y = atoi(hdr[2*12 : 3*12]) 58 r.Max.X = atoi(hdr[3*12 : 4*12]) 59 r.Max.Y = atoi(hdr[4*12 : 5*12]) 60 if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y { 61 return nil, fmt.Errorf("readimage: bad rectangle") 62 } 63 64 miny := r.Min.Y 65 maxy := r.Max.Y 66 67 l := draw.BytesPerLine(r, chan_.Depth()) 68 i, err := AllocImage(r, chan_) 69 if err != nil { 70 return nil, err 71 } 72 chunk := 32 * 1024 73 if chunk < l { 74 chunk = l 75 } 76 tmp := make([]byte, chunk) 77 for maxy > miny { 78 dy := maxy - miny 79 if dy*l > chunk { 80 dy = chunk / l 81 } 82 if dy <= 0 { 83 Free(i) 84 return nil, fmt.Errorf("readmemimage: image too wide for buffer") 85 } 86 n := dy * l 87 if _, err = io.ReadFull(fd, tmp[:n]); err != nil { 88 Free(i) 89 return nil, fmt.Errorf("readmemimage: %v", err) 90 } 91 if !new { 92 for j := 0; j < chunk; j++ { 93 tmp[j] ^= 0xFF 94 } 95 } 96 97 if _, err := loadmemimage(i, draw.Rect(r.Min.X, miny, r.Max.X, miny+dy), tmp[:n]); err != nil { 98 Free(i) 99 return nil, err 100 } 101 miny += dy 102 } 103 return i, nil 104 }