go.image/tiff: optimize reading uncompressed files from a tiff.buffer.

In case the image is read via a tiff.buffer, avoid copying the
data strip before decoding it. Remove corresponding TODO.
Speeds up reading uncompressed images (which is the common case)
and uses much less memory.

benchmark                      old ns/op    new ns/op    delta
BenchmarkDecodeCompressed        4619438      4630774   +0.25%
BenchmarkDecodeUncompressed       260809       219875  -15.70%

R=nigeltao
CC=golang-dev
https://golang.org/cl/5683050
diff --git a/tiff/buffer.go b/tiff/buffer.go
index 27533c6..d1801be 100644
--- a/tiff/buffer.go
+++ b/tiff/buffer.go
@@ -12,13 +12,8 @@
 	buf []byte
 }
 
-func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
-	o := int(off)
-	end := o + len(p)
-	if int64(end) != off+int64(len(p)) {
-		return 0, io.ErrUnexpectedEOF
-	}
-
+// fill reads data from b.r until the buffer contains at least end bytes.
+func (b *buffer) fill(end int) error {
 	m := len(b.buf)
 	if end > m {
 		if end > cap(b.buf) {
@@ -35,11 +30,31 @@
 		if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil {
 			end = m + n
 			b.buf = b.buf[:end]
-			return copy(p, b.buf[o:end]), err
+			return err
 		}
 	}
+	return nil
+}
 
-	return copy(p, b.buf[o:end]), nil
+func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
+	o := int(off)
+	end := o + len(p)
+	if int64(end) != off+int64(len(p)) {
+		return 0, io.ErrUnexpectedEOF
+	}
+
+	err := b.fill(end)
+	return copy(p, b.buf[o:end]), err
+}
+
+// Slice returns a slice of the underlying buffer. The slice contains
+// n bytes starting at offset off.
+func (b *buffer) Slice(off, n int) ([]byte, error) {
+	end := off + n
+	if err := b.fill(end); err != nil {
+		return nil, err
+	}
+	return b.buf[off:end], nil
 }
 
 // newReaderAt converts an io.Reader into an io.ReaderAt.
diff --git a/tiff/reader.go b/tiff/reader.go
index dc5a87a..0603b1e 100644
--- a/tiff/reader.go
+++ b/tiff/reader.go
@@ -397,9 +397,12 @@
 		n := int64(d.features[tStripByteCounts][i])
 		switch d.firstVal(tCompression) {
 		case cNone:
-			// TODO(bsiegert): Avoid copy if r is a tiff.buffer.
-			d.buf = make([]byte, n)
-			_, err = d.r.ReadAt(d.buf, offset)
+			if b, ok := d.r.(*buffer); ok {
+				d.buf, err = b.Slice(int(offset), int(n))
+			} else {
+				d.buf = make([]byte, n)
+				_, err = d.r.ReadAt(d.buf, offset)
+			}
 		case cLZW:
 			r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8)
 			d.buf, err = ioutil.ReadAll(r)