summaryrefslogtreecommitdiff
path: root/src/pkg/image/jpeg
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/image/jpeg')
-rw-r--r--src/pkg/image/jpeg/huffman.go6
-rw-r--r--src/pkg/image/jpeg/reader_test.go27
-rw-r--r--src/pkg/image/jpeg/scan.go21
3 files changed, 35 insertions, 19 deletions
diff --git a/src/pkg/image/jpeg/huffman.go b/src/pkg/image/jpeg/huffman.go
index 9b731fdc4..f53d873a5 100644
--- a/src/pkg/image/jpeg/huffman.go
+++ b/src/pkg/image/jpeg/huffman.go
@@ -37,6 +37,9 @@ func (d *decoder) ensureNBits(n int) error {
for d.b.n < n {
c, err := d.r.ReadByte()
if err != nil {
+ if err == io.EOF {
+ return FormatError("short Huffman data")
+ }
return err
}
d.b.a = d.b.a<<8 | uint32(c)
@@ -50,6 +53,9 @@ func (d *decoder) ensureNBits(n int) error {
if c == 0xff {
c, err = d.r.ReadByte()
if err != nil {
+ if err == io.EOF {
+ return FormatError("short Huffman data")
+ }
return err
}
if c != 0x00 {
diff --git a/src/pkg/image/jpeg/reader_test.go b/src/pkg/image/jpeg/reader_test.go
index e951e038c..926bb0434 100644
--- a/src/pkg/image/jpeg/reader_test.go
+++ b/src/pkg/image/jpeg/reader_test.go
@@ -28,6 +28,7 @@ func TestDecodeProgressive(t *testing.T) {
"../testdata/video-001.q50.444",
"../testdata/video-005.gray.q50",
"../testdata/video-005.gray.q50.2x2",
+ "../testdata/video-001.separate.dc.progression",
}
for _, tc := range testCases {
m0, err := decodeFile(tc + ".jpeg")
@@ -44,6 +45,12 @@ func TestDecodeProgressive(t *testing.T) {
t.Errorf("%s: bounds differ: %v and %v", tc, m0.Bounds(), m1.Bounds())
continue
}
+ // All of the video-*.jpeg files are 150x103.
+ if m0.Bounds() != image.Rect(0, 0, 150, 103) {
+ t.Errorf("%s: bad bounds: %v", tc, m0.Bounds())
+ continue
+ }
+
switch m0 := m0.(type) {
case *image.YCbCr:
m1 := m1.(*image.YCbCr)
@@ -84,18 +91,15 @@ func decodeFile(filename string) (image.Image, error) {
// check checks that the two pix data are equal, within the given bounds.
func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
- if len(pix0) != len(pix1) {
- return fmt.Errorf("len(pix) %d and %d differ", len(pix0), len(pix1))
- }
- if stride0 != stride1 {
- return fmt.Errorf("strides %d and %d differ", stride0, stride1)
+ if stride0 <= 0 || stride0%8 != 0 {
+ return fmt.Errorf("bad stride %d", stride0)
}
- if stride0%8 != 0 {
- return fmt.Errorf("stride %d is not a multiple of 8", stride0)
+ if stride1 <= 0 || stride1%8 != 0 {
+ return fmt.Errorf("bad stride %d", stride1)
}
// Compare the two pix data, one 8x8 block at a time.
- for y := 0; y < len(pix0)/stride0; y += 8 {
- for x := 0; x < stride0; x += 8 {
+ for y := 0; y < len(pix0)/stride0 && y < len(pix1)/stride1; y += 8 {
+ for x := 0; x < stride0 && x < stride1; x += 8 {
if x >= bounds.Max.X || y >= bounds.Max.Y {
// We don't care if the two pix data differ if the 8x8 block is
// entirely outside of the image's bounds. For example, this can
@@ -108,8 +112,9 @@ func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) erro
for j := 0; j < 8; j++ {
for i := 0; i < 8; i++ {
- index := (y+j)*stride0 + (x + i)
- if pix0[index] != pix1[index] {
+ index0 := (y+j)*stride0 + (x + i)
+ index1 := (y+j)*stride1 + (x + i)
+ if pix0[index0] != pix1[index1] {
return fmt.Errorf("blocks at (%d, %d) differ:\n%sand\n%s", x, y,
pixString(pix0, stride0, x, y),
pixString(pix1, stride1, x, y),
diff --git a/src/pkg/image/jpeg/scan.go b/src/pkg/image/jpeg/scan.go
index a69ed1748..559235d51 100644
--- a/src/pkg/image/jpeg/scan.go
+++ b/src/pkg/image/jpeg/scan.go
@@ -141,25 +141,30 @@ func (d *decoder) processSOS(n int) error {
for j := 0; j < d.comp[compIndex].h*d.comp[compIndex].v; j++ {
// The blocks are traversed one MCU at a time. For 4:2:0 chroma
// subsampling, there are four Y 8x8 blocks in every 16x16 MCU.
+ //
// For a baseline 32x16 pixel image, the Y blocks visiting order is:
// 0 1 4 5
// 2 3 6 7
//
- // For progressive images, the DC data blocks (zigStart == 0) are traversed
- // as above, but AC data blocks are traversed left to right, top to bottom:
+ // For progressive images, the interleaved scans (those with nComp > 1)
+ // are traversed as above, but non-interleaved scans are traversed left
+ // to right, top to bottom:
// 0 1 2 3
// 4 5 6 7
+ // Only DC scans (zigStart == 0) can be interleaved. AC scans must have
+ // only one component.
//
- // To further complicate matters, there is no AC data for any blocks that
- // are inside the image at the MCU level but outside the image at the pixel
- // level. For example, a 24x16 pixel 4:2:0 progressive image consists of
- // two 16x16 MCUs. The earlier scans will process 8 Y blocks:
+ // To further complicate matters, for non-interleaved scans, there is no
+ // data for any blocks that are inside the image at the MCU level but
+ // outside the image at the pixel level. For example, a 24x16 pixel 4:2:0
+ // progressive image consists of two 16x16 MCUs. The interleaved scans
+ // will process 8 Y blocks:
// 0 1 4 5
// 2 3 6 7
- // The later scans will process only 6 Y blocks:
+ // The non-interleaved scans will process only 6 Y blocks:
// 0 1 2
// 3 4 5
- if zigStart == 0 {
+ if nComp != 1 {
mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
if h0 == 1 {
my0 += j