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
This commit is contained in:
parent
996c335c4a
commit
324e6dabf0
|
@ -12,13 +12,8 @@ type buffer struct {
|
|||
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 @@ func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
|
|||
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.
|
||||
|
|
|
@ -397,9 +397,12 @@ func Decode(r io.Reader) (img image.Image, err error) {
|
|||
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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user