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  }