9fans.net/go@v0.0.5/draw/loadimage.go (about) 1 package draw 2 3 import "fmt" 4 5 // Load replaces the specified rectangle in image dst with the data, 6 // returning the number of bytes copied from data. 7 // It is an error if data is too small to supply pixels for the entire rectangle. 8 // 9 // In data, the pixels are presented one horizontal line at a time, 10 // starting with the top-left pixel of r. Each scan line starts with a new byte 11 // in the array, leaving the last byte of the previous line partially empty 12 // if necessary when i.Depth < 8. Pixels are packed as tightly as possible 13 // within a line, regardless of the rectangle being extracted. 14 // Bytes are filled from most to least significant bit order, 15 // as the x coordinate increases, aligned so that x = r.Min would appear as 16 // the leftmost pixel of its byte. 17 // Thus, for depth 1, the pixel at x offset 165 within the rectangle 18 // will be in a data byte at bit-position 0x04 regardless of the overall 19 // rectangle: 165 mod 8 equals 5, and 0x80 >> 5 equals 0x04. 20 func (dst *Image) Load(r Rectangle, data []byte) (n int, err error) { 21 dst.Display.mu.Lock() 22 defer dst.Display.mu.Unlock() 23 return dst.load(r, data) 24 } 25 26 func (dst *Image) load(r Rectangle, data []byte) (int, error) { 27 i := dst 28 chunk := i.Display.bufsize - 64 29 if !r.In(i.R) { 30 return 0, fmt.Errorf("loadimage: bad rectangle") 31 } 32 bpl := BytesPerLine(r, i.Depth) 33 n := bpl * r.Dy() 34 if n > len(data) { 35 return 0, fmt.Errorf("loadimage: insufficient data") 36 } 37 ndata := 0 38 for r.Max.Y > r.Min.Y { 39 dy := r.Max.Y - r.Min.Y 40 if dy*bpl > chunk { 41 dy = chunk / bpl 42 } 43 if dy <= 0 { 44 return 0, fmt.Errorf("loadimage: image too wide for buffer") 45 } 46 n := dy * bpl 47 a := i.Display.bufimage(21 + n) 48 a[0] = 'y' 49 bplong(a[1:], uint32(i.id)) 50 bplong(a[5:], uint32(r.Min.X)) 51 bplong(a[9:], uint32(r.Min.Y)) 52 bplong(a[13:], uint32(r.Max.X)) 53 bplong(a[17:], uint32(r.Min.Y+dy)) 54 copy(a[21:], data) 55 ndata += n 56 data = data[n:] 57 r.Min.Y += dy 58 } 59 if err := i.Display.flush(false); err != nil { 60 return ndata, err 61 } 62 return ndata, nil 63 }