summaryrefslogtreecommitdiff
path: root/libgo/go/image/jpeg/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/image/jpeg/reader.go')
-rw-r--r--libgo/go/image/jpeg/reader.go210
1 files changed, 180 insertions, 30 deletions
diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go
index 356d56220a..6d8b1d1d03 100644
--- a/libgo/go/image/jpeg/reader.go
+++ b/libgo/go/image/jpeg/reader.go
@@ -8,7 +8,6 @@
package jpeg
import (
- "bufio"
"image"
"image/color"
"io"
@@ -84,15 +83,36 @@ var unzig = [blockSize]int{
53, 60, 61, 54, 47, 55, 62, 63,
}
-// If the passed in io.Reader does not also have ReadByte, then Decode will introduce its own buffering.
+// Reader is deprecated.
type Reader interface {
+ io.ByteReader
io.Reader
- ReadByte() (c byte, err error)
+}
+
+// bits holds the unprocessed bits that have been taken from the byte-stream.
+// The n least significant bits of a form the unread bits, to be read in MSB to
+// LSB order.
+type bits struct {
+ a uint32 // accumulator.
+ m uint32 // mask. m==1<<(n-1) when n>0, with m==0 when n==0.
+ n int32 // the number of unread bits in a.
}
type decoder struct {
- r Reader
- b bits
+ r io.Reader
+ bits bits
+ // bytes is a byte buffer, similar to a bufio.Reader, except that it
+ // has to be able to unread more than 1 byte, due to byte stuffing.
+ // Byte stuffing is specified in section F.1.2.3.
+ bytes struct {
+ // buf[i:j] are the buffered bytes read from the underlying
+ // io.Reader that haven't yet been passed further on.
+ buf [4096]byte
+ i, j int
+ // nUnreadable is the number of bytes to back up i after
+ // overshooting. It can be 0, 1 or 2.
+ nUnreadable int
+ }
width, height int
img1 *image.Gray
img3 *image.YCbCr
@@ -104,21 +124,160 @@ type decoder struct {
progCoeffs [nColorComponent][]block // Saved state between progressive-mode scans.
huff [maxTc + 1][maxTh + 1]huffman
quant [maxTq + 1]block // Quantization tables, in zig-zag order.
- tmp [1024]byte
+ tmp [blockSize + 1]byte
+}
+
+// fill fills up the d.bytes.buf buffer from the underlying io.Reader. It
+// should only be called when there are no unread bytes in d.bytes.
+func (d *decoder) fill() error {
+ if d.bytes.i != d.bytes.j {
+ panic("jpeg: fill called when unread bytes exist")
+ }
+ // Move the last 2 bytes to the start of the buffer, in case we need
+ // to call unreadByteStuffedByte.
+ if d.bytes.j > 2 {
+ d.bytes.buf[0] = d.bytes.buf[d.bytes.j-2]
+ d.bytes.buf[1] = d.bytes.buf[d.bytes.j-1]
+ d.bytes.i, d.bytes.j = 2, 2
+ }
+ // Fill in the rest of the buffer.
+ n, err := d.r.Read(d.bytes.buf[d.bytes.j:])
+ d.bytes.j += n
+ if n > 0 {
+ err = nil
+ }
+ return err
+}
+
+// unreadByteStuffedByte undoes the most recent readByteStuffedByte call,
+// giving a byte of data back from d.bits to d.bytes. The Huffman look-up table
+// requires at least 8 bits for look-up, which means that Huffman decoding can
+// sometimes overshoot and read one or two too many bytes. Two-byte overshoot
+// can happen when expecting to read a 0xff 0x00 byte-stuffed byte.
+func (d *decoder) unreadByteStuffedByte() {
+ if d.bytes.nUnreadable == 0 {
+ panic("jpeg: unreadByteStuffedByte call cannot be fulfilled")
+ }
+ d.bytes.i -= d.bytes.nUnreadable
+ d.bytes.nUnreadable = 0
+ if d.bits.n >= 8 {
+ d.bits.a >>= 8
+ d.bits.n -= 8
+ d.bits.m >>= 8
+ }
+}
+
+// readByte returns the next byte, whether buffered or not buffered. It does
+// not care about byte stuffing.
+func (d *decoder) readByte() (x byte, err error) {
+ for d.bytes.i == d.bytes.j {
+ if err = d.fill(); err != nil {
+ return 0, err
+ }
+ }
+ x = d.bytes.buf[d.bytes.i]
+ d.bytes.i++
+ d.bytes.nUnreadable = 0
+ return x, nil
+}
+
+// errMissingFF00 means that readByteStuffedByte encountered an 0xff byte (a
+// marker byte) that wasn't the expected byte-stuffed sequence 0xff, 0x00.
+var errMissingFF00 = FormatError("missing 0xff00 sequence")
+
+// readByteStuffedByte is like readByte but is for byte-stuffed Huffman data.
+func (d *decoder) readByteStuffedByte() (x byte, err error) {
+ // Take the fast path if d.bytes.buf contains at least two bytes.
+ if d.bytes.i+2 <= d.bytes.j {
+ x = d.bytes.buf[d.bytes.i]
+ d.bytes.i++
+ d.bytes.nUnreadable = 1
+ if x != 0xff {
+ return x, err
+ }
+ if d.bytes.buf[d.bytes.i] != 0x00 {
+ return 0, errMissingFF00
+ }
+ d.bytes.i++
+ d.bytes.nUnreadable = 2
+ return 0xff, nil
+ }
+
+ x, err = d.readByte()
+ if err != nil {
+ return 0, err
+ }
+ if x != 0xff {
+ d.bytes.nUnreadable = 1
+ return x, nil
+ }
+
+ x, err = d.readByte()
+ if err != nil {
+ d.bytes.nUnreadable = 1
+ return 0, err
+ }
+ d.bytes.nUnreadable = 2
+ if x != 0x00 {
+ return 0, errMissingFF00
+ }
+ return 0xff, nil
}
-// Reads and ignores the next n bytes.
+// readFull reads exactly len(p) bytes into p. It does not care about byte
+// stuffing.
+func (d *decoder) readFull(p []byte) error {
+ // Unread the overshot bytes, if any.
+ if d.bytes.nUnreadable != 0 {
+ if d.bits.n >= 8 {
+ d.unreadByteStuffedByte()
+ }
+ d.bytes.nUnreadable = 0
+ }
+
+ for {
+ n := copy(p, d.bytes.buf[d.bytes.i:d.bytes.j])
+ p = p[n:]
+ d.bytes.i += n
+ if len(p) == 0 {
+ break
+ }
+ if err := d.fill(); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return err
+ }
+ }
+ return nil
+}
+
+// ignore ignores the next n bytes.
func (d *decoder) ignore(n int) error {
- for n > 0 {
- m := len(d.tmp)
+ // Unread the overshot bytes, if any.
+ if d.bytes.nUnreadable != 0 {
+ if d.bits.n >= 8 {
+ d.unreadByteStuffedByte()
+ }
+ d.bytes.nUnreadable = 0
+ }
+
+ for {
+ m := d.bytes.j - d.bytes.i
if m > n {
m = n
}
- _, err := io.ReadFull(d.r, d.tmp[0:m])
- if err != nil {
+ d.bytes.i += m
+ n -= m
+ if n == 0 {
+ break
+ }
+ if err := d.fill(); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
return err
}
- n -= m
}
return nil
}
@@ -133,8 +292,7 @@ func (d *decoder) processSOF(n int) error {
default:
return UnsupportedError("SOF has wrong length")
}
- _, err := io.ReadFull(d.r, d.tmp[:n])
- if err != nil {
+ if err := d.readFull(d.tmp[:n]); err != nil {
return err
}
// We only support 8-bit precision.
@@ -187,8 +345,7 @@ func (d *decoder) processSOF(n int) error {
func (d *decoder) processDQT(n int) error {
const qtLength = 1 + blockSize
for ; n >= qtLength; n -= qtLength {
- _, err := io.ReadFull(d.r, d.tmp[0:qtLength])
- if err != nil {
+ if err := d.readFull(d.tmp[:qtLength]); err != nil {
return err
}
pq := d.tmp[0] >> 4
@@ -214,8 +371,7 @@ func (d *decoder) processDRI(n int) error {
if n != 2 {
return FormatError("DRI has wrong length")
}
- _, err := io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err := d.readFull(d.tmp[:2]); err != nil {
return err
}
d.ri = int(d.tmp[0])<<8 + int(d.tmp[1])
@@ -224,15 +380,10 @@ func (d *decoder) processDRI(n int) error {
// decode reads a JPEG image from r and returns it as an image.Image.
func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
- if rr, ok := r.(Reader); ok {
- d.r = rr
- } else {
- d.r = bufio.NewReader(r)
- }
+ d.r = r
// Check for the Start Of Image marker.
- _, err := io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err := d.readFull(d.tmp[:2]); err != nil {
return nil, err
}
if d.tmp[0] != 0xff || d.tmp[1] != soiMarker {
@@ -241,7 +392,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Process the remaining segments until the End Of Image marker.
for {
- _, err := io.ReadFull(d.r, d.tmp[0:2])
+ err := d.readFull(d.tmp[:2])
if err != nil {
return nil, err
}
@@ -267,7 +418,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Note that extraneous 0xff bytes in e.g. SOS data are escaped as
// "\xff\x00", and so are detected a little further down below.
d.tmp[0] = d.tmp[1]
- d.tmp[1], err = d.r.ReadByte()
+ d.tmp[1], err = d.readByte()
if err != nil {
return nil, err
}
@@ -280,7 +431,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
for marker == 0xff {
// Section B.1.1.2 says, "Any marker may optionally be preceded by any
// number of fill bytes, which are bytes assigned code X'FF'".
- marker, err = d.r.ReadByte()
+ marker, err = d.readByte()
if err != nil {
return nil, err
}
@@ -300,8 +451,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
// Read the 16-bit length of the segment. The value includes the 2 bytes for the
// length itself, so we subtract 2 to get the number of remaining bytes.
- _, err = io.ReadFull(d.r, d.tmp[0:2])
- if err != nil {
+ if err = d.readFull(d.tmp[:2]); err != nil {
return nil, err
}
n := int(d.tmp[0])<<8 + int(d.tmp[1]) - 2