package draw9 import ( "bitbucket.org/mischief/draw9/color9" "fmt" "io" "strings" ) func (d *Display) creadimage(rd io.Reader) (*Image, error) { fd := rd hdr := make([]byte, 5*12) _, err := io.ReadFull(fd, hdr) if err != nil { return nil, fmt.Errorf("reading image header: %v", err) } /* * distinguish new channel descriptor from old ldepth. * channel descriptors have letters as well as numbers, * while ldepths are a single digit formatted as %-11d. */ new := false for m := 0; m < 10; m++ { if hdr[m] != ' ' { new = true break } } if hdr[11] != ' ' { return nil, fmt.Errorf("creadimage: bad format") } var pix color9.Pix if new { pix, err = color9.ParsePix(strings.TrimSpace(string(hdr[:12]))) if err != nil { return nil, fmt.Errorf("creadimage: %v", err) } } else { ldepth := int(hdr[10]) - '0' if ldepth < 0 || ldepth > 3 { return nil, fmt.Errorf("creadimage: bad ldepth %d", ldepth) } pix = ldepthToPix[ldepth] } r := ator(hdr[1*12:]) if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y { return nil, fmt.Errorf("creadimage: bad rectangle") } var i *Image if d != nil { i, err = d.allocImage(r, pix, false, 0) if err != nil { return nil, err } } else { i = &Image{R: r, Pix: pix, Depth: pix.Depth()} } ncblock := compblocksize(r, pix.Depth()) buf := make([]byte, ncblock) miny := r.Min.Y for miny != r.Max.Y { if _, err = io.ReadFull(fd, hdr[:2*12]); err != nil { goto Errout } maxy := atoi(hdr[0*12:]) nb := atoi(hdr[1*12:]) if maxy <= miny || r.Max.Y < maxy { err = fmt.Errorf("creadimage: bad maxy %d", maxy) goto Errout } if nb <= 0 || ncblock < nb { err = fmt.Errorf("creadimage: bad count %d", nb) goto Errout } if _, err = io.ReadFull(fd, buf[:nb]); err != nil { goto Errout } if d != nil { a := d.bufimage(21 + nb) // XXX err if err != nil { goto Errout } a[0] = 'Y' bplong(a[1:], i.ID) bplong(a[5:], uint32(r.Min.X)) bplong(a[9:], uint32(miny)) bplong(a[13:], uint32(r.Max.X)) bplong(a[17:], uint32(maxy)) if !new { // old image: flip the data bits twiddlecompressed(buf[:nb]) } copy(a[21:], buf) } miny = maxy } return i, nil Errout: if d != nil { i.free() } return nil, err }