]> Cypherpunks repositories - gostls13.git/commitdiff
image/jpeg: re-organize the processSOS code.
authorNigel Tao <nigeltao@golang.org>
Mon, 15 Oct 2012 02:28:30 +0000 (13:28 +1100)
committerNigel Tao <nigeltao@golang.org>
Mon, 15 Oct 2012 02:28:30 +0000 (13:28 +1100)
This is a straight copy/paste, and the deletion of a TODO. There are
no other changes.

R=r
CC=golang-dev
https://golang.org/cl/6687049

src/pkg/image/jpeg/reader.go
src/pkg/image/jpeg/scan.go

index bd8fef12f50abb0b5aeec4eb4eab7c817a382948..c28dc8807c5d47ff92fcaaa6646ffd80773f0017 100644 (file)
@@ -196,324 +196,6 @@ func (d *decoder) processDQT(n int) error {
        return nil
 }
 
-// makeImg allocates and initializes the destination image.
-func (d *decoder) makeImg(h0, v0, mxx, myy int) {
-       if d.nComp == nGrayComponent {
-               m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
-               d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
-               return
-       }
-       var subsampleRatio image.YCbCrSubsampleRatio
-       switch {
-       case h0 == 1 && v0 == 1:
-               subsampleRatio = image.YCbCrSubsampleRatio444
-       case h0 == 1 && v0 == 2:
-               subsampleRatio = image.YCbCrSubsampleRatio440
-       case h0 == 2 && v0 == 1:
-               subsampleRatio = image.YCbCrSubsampleRatio422
-       case h0 == 2 && v0 == 2:
-               subsampleRatio = image.YCbCrSubsampleRatio420
-       default:
-               panic("unreachable")
-       }
-       m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
-       d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
-}
-
-// TODO(nigeltao): move processSOS to scan.go.
-
-// Specified in section B.2.3.
-func (d *decoder) processSOS(n int) error {
-       if d.nComp == 0 {
-               return FormatError("missing SOF marker")
-       }
-       if n < 6 || 4+2*d.nComp < n || n%2 != 0 {
-               return FormatError("SOS has wrong length")
-       }
-       _, err := io.ReadFull(d.r, d.tmp[:n])
-       if err != nil {
-               return err
-       }
-       nComp := int(d.tmp[0])
-       if n != 4+2*nComp {
-               return FormatError("SOS length inconsistent with number of components")
-       }
-       var scan [nColorComponent]struct {
-               compIndex uint8
-               td        uint8 // DC table selector.
-               ta        uint8 // AC table selector.
-       }
-       for i := 0; i < nComp; i++ {
-               cs := d.tmp[1+2*i] // Component selector.
-               compIndex := -1
-               for j, comp := range d.comp {
-                       if cs == comp.c {
-                               compIndex = j
-                       }
-               }
-               if compIndex < 0 {
-                       return FormatError("unknown component selector")
-               }
-               scan[i].compIndex = uint8(compIndex)
-               scan[i].td = d.tmp[2+2*i] >> 4
-               scan[i].ta = d.tmp[2+2*i] & 0x0f
-       }
-
-       // zigStart and zigEnd are the spectral selection bounds.
-       // ah and al are the successive approximation high and low values.
-       // The spec calls these values Ss, Se, Ah and Al.
-       //
-       // For progressive JPEGs, these are the two more-or-less independent
-       // aspects of progression. Spectral selection progression is when not
-       // all of a block's 64 DCT coefficients are transmitted in one pass.
-       // For example, three passes could transmit coefficient 0 (the DC
-       // component), coefficients 1-5, and coefficients 6-63, in zig-zag
-       // order. Successive approximation is when not all of the bits of a
-       // band of coefficients are transmitted in one pass. For example,
-       // three passes could transmit the 6 most significant bits, followed
-       // by the second-least significant bit, followed by the least
-       // significant bit.
-       //
-       // For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
-       zigStart, zigEnd, ah, al := 0, blockSize-1, uint(0), uint(0)
-       if d.progressive {
-               zigStart = int(d.tmp[1+2*nComp])
-               zigEnd = int(d.tmp[2+2*nComp])
-               ah = uint(d.tmp[3+2*nComp] >> 4)
-               al = uint(d.tmp[3+2*nComp] & 0x0f)
-               if (zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || blockSize <= zigEnd {
-                       return FormatError("bad spectral selection bounds")
-               }
-               if zigStart != 0 && nComp != 1 {
-                       return FormatError("progressive AC coefficients for more than one component")
-               }
-               if ah != 0 && ah != al+1 {
-                       return FormatError("bad successive approximation values")
-               }
-       }
-
-       // mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
-       h0, v0 := d.comp[0].h, d.comp[0].v // The h and v values from the Y components.
-       mxx := (d.width + 8*h0 - 1) / (8 * h0)
-       myy := (d.height + 8*v0 - 1) / (8 * v0)
-       if d.img1 == nil && d.img3 == nil {
-               d.makeImg(h0, v0, mxx, myy)
-               if d.progressive {
-                       for i := 0; i < nComp; i++ {
-                               compIndex := scan[i].compIndex
-                               d.progCoeffs[compIndex] = make([]block, mxx*myy*d.comp[compIndex].h*d.comp[compIndex].v)
-                       }
-               }
-       }
-
-       d.b = bits{}
-       mcu, expectedRST := 0, uint8(rst0Marker)
-       var (
-               // b is the decoded coefficients, in natural (not zig-zag) order.
-               b  block
-               dc [nColorComponent]int
-               // mx0 and my0 are the location of the current (in terms of 8x8 blocks).
-               // For example, with 4:2:0 chroma subsampling, the block whose top left
-               // pixel co-ordinates are (16, 8) is the third block in the first row:
-               // mx0 is 2 and my0 is 0, even though the pixel is in the second MCU.
-               // TODO(nigeltao): rename mx0 and my0 to bx and by?
-               mx0, my0   int
-               blockCount int
-       )
-       for my := 0; my < myy; my++ {
-               for mx := 0; mx < mxx; mx++ {
-                       for i := 0; i < nComp; i++ {
-                               compIndex := scan[i].compIndex
-                               qt := &d.quant[d.comp[compIndex].tq]
-                               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:
-                                       //      0 1 2 3
-                                       //      4 5 6 7
-                                       //
-                                       // 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:
-                                       //      0 1 4 5
-                                       //      2 3 6 7
-                                       // The later scans will process only 6 Y blocks:
-                                       //      0 1 2
-                                       //      3 4 5
-                                       if zigStart == 0 {
-                                               mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
-                                               if h0 == 1 {
-                                                       my0 += j
-                                               } else {
-                                                       mx0 += j % 2
-                                                       my0 += j / 2
-                                               }
-                                       } else {
-                                               q := mxx * d.comp[compIndex].h
-                                               mx0 = blockCount % q
-                                               my0 = blockCount / q
-                                               blockCount++
-                                               if mx0*8 >= d.width || my0*8 >= d.height {
-                                                       continue
-                                               }
-                                       }
-
-                                       // Load the previous partially decoded coefficients, if applicable.
-                                       if d.progressive {
-                                               b = d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0]
-                                       } else {
-                                               b = block{}
-                                       }
-
-                                       if ah != 0 {
-                                               if err := d.refine(&b, &d.huff[acTable][scan[i].ta], zigStart, zigEnd, 1<<al); err != nil {
-                                                       return err
-                                               }
-                                       } else {
-                                               zig := zigStart
-                                               if zig == 0 {
-                                                       zig++
-                                                       // Decode the DC coefficient, as specified in section F.2.2.1.
-                                                       value, err := d.decodeHuffman(&d.huff[dcTable][scan[i].td])
-                                                       if err != nil {
-                                                               return err
-                                                       }
-                                                       if value > 16 {
-                                                               return UnsupportedError("excessive DC component")
-                                                       }
-                                                       dcDelta, err := d.receiveExtend(value)
-                                                       if err != nil {
-                                                               return err
-                                                       }
-                                                       dc[compIndex] += dcDelta
-                                                       b[0] = dc[compIndex] << al
-                                               }
-
-                                               if zig <= zigEnd && d.eobRun > 0 {
-                                                       d.eobRun--
-                                               } else {
-                                                       // Decode the AC coefficients, as specified in section F.2.2.2.
-                                                       for ; zig <= zigEnd; zig++ {
-                                                               value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
-                                                               if err != nil {
-                                                                       return err
-                                                               }
-                                                               val0 := value >> 4
-                                                               val1 := value & 0x0f
-                                                               if val1 != 0 {
-                                                                       zig += int(val0)
-                                                                       if zig > zigEnd {
-                                                                               break
-                                                                       }
-                                                                       ac, err := d.receiveExtend(val1)
-                                                                       if err != nil {
-                                                                               return err
-                                                                       }
-                                                                       b[unzig[zig]] = ac << al
-                                                               } else {
-                                                                       if val0 != 0x0f {
-                                                                               d.eobRun = uint16(1 << val0)
-                                                                               if val0 != 0 {
-                                                                                       bits, err := d.decodeBits(int(val0))
-                                                                                       if err != nil {
-                                                                                               return err
-                                                                                       }
-                                                                                       d.eobRun |= uint16(bits)
-                                                                               }
-                                                                               d.eobRun--
-                                                                               break
-                                                                       }
-                                                                       zig += 0x0f
-                                                               }
-                                                       }
-                                               }
-                                       }
-
-                                       if d.progressive {
-                                               if zigEnd != blockSize-1 || al != 0 {
-                                                       // We haven't completely decoded this 8x8 block. Save the coefficients.
-                                                       d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0] = b
-                                                       // At this point, we could execute the rest of the loop body to dequantize and
-                                                       // perform the inverse DCT, to save early stages of a progressive image to the
-                                                       // *image.YCbCr buffers (the whole point of progressive encoding), but in Go,
-                                                       // the jpeg.Decode function does not return until the entire image is decoded,
-                                                       // so we "continue" here to avoid wasted computation.
-                                                       continue
-                                               }
-                                       }
-
-                                       // Dequantize, perform the inverse DCT and store the block to the image.
-                                       for zig := 0; zig < blockSize; zig++ {
-                                               b[unzig[zig]] *= qt[zig]
-                                       }
-                                       idct(&b)
-                                       dst, stride := []byte(nil), 0
-                                       if d.nComp == nGrayComponent {
-                                               dst, stride = d.img1.Pix[8*(my0*d.img1.Stride+mx0):], d.img1.Stride
-                                       } else {
-                                               switch compIndex {
-                                               case 0:
-                                                       dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
-                                               case 1:
-                                                       dst, stride = d.img3.Cb[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
-                                               case 2:
-                                                       dst, stride = d.img3.Cr[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
-                                               default:
-                                                       return UnsupportedError("too many components")
-                                               }
-                                       }
-                                       // Level shift by +128, clip to [0, 255], and write to dst.
-                                       for y := 0; y < 8; y++ {
-                                               y8 := y * 8
-                                               yStride := y * stride
-                                               for x := 0; x < 8; x++ {
-                                                       c := b[y8+x]
-                                                       if c < -128 {
-                                                               c = 0
-                                                       } else if c > 127 {
-                                                               c = 255
-                                                       } else {
-                                                               c += 128
-                                                       }
-                                                       dst[yStride+x] = uint8(c)
-                                               }
-                                       }
-                               } // for j
-                       } // for i
-                       mcu++
-                       if d.ri > 0 && mcu%d.ri == 0 && mcu < mxx*myy {
-                               // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
-                               // but this one assumes well-formed input, and hence the restart marker follows immediately.
-                               _, err := io.ReadFull(d.r, d.tmp[0:2])
-                               if err != nil {
-                                       return err
-                               }
-                               if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
-                                       return FormatError("bad RST marker")
-                               }
-                               expectedRST++
-                               if expectedRST == rst7Marker+1 {
-                                       expectedRST = rst0Marker
-                               }
-                               // Reset the Huffman decoder.
-                               d.b = bits{}
-                               // Reset the DC components, as per section F.2.1.3.1.
-                               dc = [nColorComponent]int{}
-                               // Reset the progressive decoder state, as per section G.1.2.2.
-                               d.eobRun = 0
-                       }
-               } // for mx
-       } // for my
-
-       return nil
-}
-
 // Specified in section B.2.4.4.
 func (d *decoder) processDRI(n int) error {
        if n != 2 {
index c918971f288b5c0b5c2e92716324128d73c911b7..fd491ed083b7db1030f9b7251ee1d7e1f5c01fd1 100644 (file)
@@ -4,6 +4,327 @@
 
 package jpeg
 
+import (
+       "image"
+       "io"
+)
+
+// makeImg allocates and initializes the destination image.
+func (d *decoder) makeImg(h0, v0, mxx, myy int) {
+       if d.nComp == nGrayComponent {
+               m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
+               d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
+               return
+       }
+       var subsampleRatio image.YCbCrSubsampleRatio
+       switch {
+       case h0 == 1 && v0 == 1:
+               subsampleRatio = image.YCbCrSubsampleRatio444
+       case h0 == 1 && v0 == 2:
+               subsampleRatio = image.YCbCrSubsampleRatio440
+       case h0 == 2 && v0 == 1:
+               subsampleRatio = image.YCbCrSubsampleRatio422
+       case h0 == 2 && v0 == 2:
+               subsampleRatio = image.YCbCrSubsampleRatio420
+       default:
+               panic("unreachable")
+       }
+       m := image.NewYCbCr(image.Rect(0, 0, 8*h0*mxx, 8*v0*myy), subsampleRatio)
+       d.img3 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.YCbCr)
+}
+
+// Specified in section B.2.3.
+func (d *decoder) processSOS(n int) error {
+       if d.nComp == 0 {
+               return FormatError("missing SOF marker")
+       }
+       if n < 6 || 4+2*d.nComp < n || n%2 != 0 {
+               return FormatError("SOS has wrong length")
+       }
+       _, err := io.ReadFull(d.r, d.tmp[:n])
+       if err != nil {
+               return err
+       }
+       nComp := int(d.tmp[0])
+       if n != 4+2*nComp {
+               return FormatError("SOS length inconsistent with number of components")
+       }
+       var scan [nColorComponent]struct {
+               compIndex uint8
+               td        uint8 // DC table selector.
+               ta        uint8 // AC table selector.
+       }
+       for i := 0; i < nComp; i++ {
+               cs := d.tmp[1+2*i] // Component selector.
+               compIndex := -1
+               for j, comp := range d.comp {
+                       if cs == comp.c {
+                               compIndex = j
+                       }
+               }
+               if compIndex < 0 {
+                       return FormatError("unknown component selector")
+               }
+               scan[i].compIndex = uint8(compIndex)
+               scan[i].td = d.tmp[2+2*i] >> 4
+               scan[i].ta = d.tmp[2+2*i] & 0x0f
+       }
+
+       // zigStart and zigEnd are the spectral selection bounds.
+       // ah and al are the successive approximation high and low values.
+       // The spec calls these values Ss, Se, Ah and Al.
+       //
+       // For progressive JPEGs, these are the two more-or-less independent
+       // aspects of progression. Spectral selection progression is when not
+       // all of a block's 64 DCT coefficients are transmitted in one pass.
+       // For example, three passes could transmit coefficient 0 (the DC
+       // component), coefficients 1-5, and coefficients 6-63, in zig-zag
+       // order. Successive approximation is when not all of the bits of a
+       // band of coefficients are transmitted in one pass. For example,
+       // three passes could transmit the 6 most significant bits, followed
+       // by the second-least significant bit, followed by the least
+       // significant bit.
+       //
+       // For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
+       zigStart, zigEnd, ah, al := 0, blockSize-1, uint(0), uint(0)
+       if d.progressive {
+               zigStart = int(d.tmp[1+2*nComp])
+               zigEnd = int(d.tmp[2+2*nComp])
+               ah = uint(d.tmp[3+2*nComp] >> 4)
+               al = uint(d.tmp[3+2*nComp] & 0x0f)
+               if (zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || blockSize <= zigEnd {
+                       return FormatError("bad spectral selection bounds")
+               }
+               if zigStart != 0 && nComp != 1 {
+                       return FormatError("progressive AC coefficients for more than one component")
+               }
+               if ah != 0 && ah != al+1 {
+                       return FormatError("bad successive approximation values")
+               }
+       }
+
+       // mxx and myy are the number of MCUs (Minimum Coded Units) in the image.
+       h0, v0 := d.comp[0].h, d.comp[0].v // The h and v values from the Y components.
+       mxx := (d.width + 8*h0 - 1) / (8 * h0)
+       myy := (d.height + 8*v0 - 1) / (8 * v0)
+       if d.img1 == nil && d.img3 == nil {
+               d.makeImg(h0, v0, mxx, myy)
+               if d.progressive {
+                       for i := 0; i < nComp; i++ {
+                               compIndex := scan[i].compIndex
+                               d.progCoeffs[compIndex] = make([]block, mxx*myy*d.comp[compIndex].h*d.comp[compIndex].v)
+                       }
+               }
+       }
+
+       d.b = bits{}
+       mcu, expectedRST := 0, uint8(rst0Marker)
+       var (
+               // b is the decoded coefficients, in natural (not zig-zag) order.
+               b  block
+               dc [nColorComponent]int
+               // mx0 and my0 are the location of the current (in terms of 8x8 blocks).
+               // For example, with 4:2:0 chroma subsampling, the block whose top left
+               // pixel co-ordinates are (16, 8) is the third block in the first row:
+               // mx0 is 2 and my0 is 0, even though the pixel is in the second MCU.
+               // TODO(nigeltao): rename mx0 and my0 to bx and by?
+               mx0, my0   int
+               blockCount int
+       )
+       for my := 0; my < myy; my++ {
+               for mx := 0; mx < mxx; mx++ {
+                       for i := 0; i < nComp; i++ {
+                               compIndex := scan[i].compIndex
+                               qt := &d.quant[d.comp[compIndex].tq]
+                               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:
+                                       //      0 1 2 3
+                                       //      4 5 6 7
+                                       //
+                                       // 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:
+                                       //      0 1 4 5
+                                       //      2 3 6 7
+                                       // The later scans will process only 6 Y blocks:
+                                       //      0 1 2
+                                       //      3 4 5
+                                       if zigStart == 0 {
+                                               mx0, my0 = d.comp[compIndex].h*mx, d.comp[compIndex].v*my
+                                               if h0 == 1 {
+                                                       my0 += j
+                                               } else {
+                                                       mx0 += j % 2
+                                                       my0 += j / 2
+                                               }
+                                       } else {
+                                               q := mxx * d.comp[compIndex].h
+                                               mx0 = blockCount % q
+                                               my0 = blockCount / q
+                                               blockCount++
+                                               if mx0*8 >= d.width || my0*8 >= d.height {
+                                                       continue
+                                               }
+                                       }
+
+                                       // Load the previous partially decoded coefficients, if applicable.
+                                       if d.progressive {
+                                               b = d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0]
+                                       } else {
+                                               b = block{}
+                                       }
+
+                                       if ah != 0 {
+                                               if err := d.refine(&b, &d.huff[acTable][scan[i].ta], zigStart, zigEnd, 1<<al); err != nil {
+                                                       return err
+                                               }
+                                       } else {
+                                               zig := zigStart
+                                               if zig == 0 {
+                                                       zig++
+                                                       // Decode the DC coefficient, as specified in section F.2.2.1.
+                                                       value, err := d.decodeHuffman(&d.huff[dcTable][scan[i].td])
+                                                       if err != nil {
+                                                               return err
+                                                       }
+                                                       if value > 16 {
+                                                               return UnsupportedError("excessive DC component")
+                                                       }
+                                                       dcDelta, err := d.receiveExtend(value)
+                                                       if err != nil {
+                                                               return err
+                                                       }
+                                                       dc[compIndex] += dcDelta
+                                                       b[0] = dc[compIndex] << al
+                                               }
+
+                                               if zig <= zigEnd && d.eobRun > 0 {
+                                                       d.eobRun--
+                                               } else {
+                                                       // Decode the AC coefficients, as specified in section F.2.2.2.
+                                                       for ; zig <= zigEnd; zig++ {
+                                                               value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
+                                                               if err != nil {
+                                                                       return err
+                                                               }
+                                                               val0 := value >> 4
+                                                               val1 := value & 0x0f
+                                                               if val1 != 0 {
+                                                                       zig += int(val0)
+                                                                       if zig > zigEnd {
+                                                                               break
+                                                                       }
+                                                                       ac, err := d.receiveExtend(val1)
+                                                                       if err != nil {
+                                                                               return err
+                                                                       }
+                                                                       b[unzig[zig]] = ac << al
+                                                               } else {
+                                                                       if val0 != 0x0f {
+                                                                               d.eobRun = uint16(1 << val0)
+                                                                               if val0 != 0 {
+                                                                                       bits, err := d.decodeBits(int(val0))
+                                                                                       if err != nil {
+                                                                                               return err
+                                                                                       }
+                                                                                       d.eobRun |= uint16(bits)
+                                                                               }
+                                                                               d.eobRun--
+                                                                               break
+                                                                       }
+                                                                       zig += 0x0f
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if d.progressive {
+                                               if zigEnd != blockSize-1 || al != 0 {
+                                                       // We haven't completely decoded this 8x8 block. Save the coefficients.
+                                                       d.progCoeffs[compIndex][my0*mxx*d.comp[compIndex].h+mx0] = b
+                                                       // At this point, we could execute the rest of the loop body to dequantize and
+                                                       // perform the inverse DCT, to save early stages of a progressive image to the
+                                                       // *image.YCbCr buffers (the whole point of progressive encoding), but in Go,
+                                                       // the jpeg.Decode function does not return until the entire image is decoded,
+                                                       // so we "continue" here to avoid wasted computation.
+                                                       continue
+                                               }
+                                       }
+
+                                       // Dequantize, perform the inverse DCT and store the block to the image.
+                                       for zig := 0; zig < blockSize; zig++ {
+                                               b[unzig[zig]] *= qt[zig]
+                                       }
+                                       idct(&b)
+                                       dst, stride := []byte(nil), 0
+                                       if d.nComp == nGrayComponent {
+                                               dst, stride = d.img1.Pix[8*(my0*d.img1.Stride+mx0):], d.img1.Stride
+                                       } else {
+                                               switch compIndex {
+                                               case 0:
+                                                       dst, stride = d.img3.Y[8*(my0*d.img3.YStride+mx0):], d.img3.YStride
+                                               case 1:
+                                                       dst, stride = d.img3.Cb[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+                                               case 2:
+                                                       dst, stride = d.img3.Cr[8*(my0*d.img3.CStride+mx0):], d.img3.CStride
+                                               default:
+                                                       return UnsupportedError("too many components")
+                                               }
+                                       }
+                                       // Level shift by +128, clip to [0, 255], and write to dst.
+                                       for y := 0; y < 8; y++ {
+                                               y8 := y * 8
+                                               yStride := y * stride
+                                               for x := 0; x < 8; x++ {
+                                                       c := b[y8+x]
+                                                       if c < -128 {
+                                                               c = 0
+                                                       } else if c > 127 {
+                                                               c = 255
+                                                       } else {
+                                                               c += 128
+                                                       }
+                                                       dst[yStride+x] = uint8(c)
+                                               }
+                                       }
+                               } // for j
+                       } // for i
+                       mcu++
+                       if d.ri > 0 && mcu%d.ri == 0 && mcu < mxx*myy {
+                               // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
+                               // but this one assumes well-formed input, and hence the restart marker follows immediately.
+                               _, err := io.ReadFull(d.r, d.tmp[0:2])
+                               if err != nil {
+                                       return err
+                               }
+                               if d.tmp[0] != 0xff || d.tmp[1] != expectedRST {
+                                       return FormatError("bad RST marker")
+                               }
+                               expectedRST++
+                               if expectedRST == rst7Marker+1 {
+                                       expectedRST = rst0Marker
+                               }
+                               // Reset the Huffman decoder.
+                               d.b = bits{}
+                               // Reset the DC components, as per section F.2.1.3.1.
+                               dc = [nColorComponent]int{}
+                               // Reset the progressive decoder state, as per section G.1.2.2.
+                               d.eobRun = 0
+                       }
+               } // for mx
+       } // for my
+
+       return nil
+}
+
 // refine decodes a successive approximation refinement block, as specified in
 // section G.1.2.
 func (d *decoder) refine(b *block, h *huffman, zigStart, zigEnd, delta int) error {