summaryrefslogtreecommitdiff
path: root/libgo/go/image/jpeg/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/image/jpeg/scan.go')
-rw-r--r--libgo/go/image/jpeg/scan.go128
1 files changed, 79 insertions, 49 deletions
diff --git a/libgo/go/image/jpeg/scan.go b/libgo/go/image/jpeg/scan.go
index 99734c01af..e1104d27c2 100644
--- a/libgo/go/image/jpeg/scan.go
+++ b/libgo/go/image/jpeg/scan.go
@@ -173,7 +173,6 @@ func (d *decoder) processSOS(n int) error {
compIndex := scan[i].compIndex
hi := d.comp[compIndex].h
vi := d.comp[compIndex].v
- qt := &d.quant[d.comp[compIndex].tq]
for j := 0; j < hi*vi; 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.
@@ -286,55 +285,19 @@ func (d *decoder) processSOS(n int) error {
}
if d.progressive {
- if zigEnd != blockSize-1 || al != 0 {
- // We haven't completely decoded this 8x8 block. Save the coefficients.
- d.progCoeffs[compIndex][by*mxx*hi+bx] = 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]
+ // Save the coefficients.
+ d.progCoeffs[compIndex][by*mxx*hi+bx] = b
+ // At this point, we could call reconstructBlock 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. Instead, reconstructBlock is called on each
+ // accumulated block by the reconstructProgressiveImage method after all of the
+ // SOS markers are processed.
+ continue
}
- idct(&b)
- dst, stride := []byte(nil), 0
- if d.nComp == 1 {
- dst, stride = d.img1.Pix[8*(by*d.img1.Stride+bx):], d.img1.Stride
- } else {
- switch compIndex {
- case 0:
- dst, stride = d.img3.Y[8*(by*d.img3.YStride+bx):], d.img3.YStride
- case 1:
- dst, stride = d.img3.Cb[8*(by*d.img3.CStride+bx):], d.img3.CStride
- case 2:
- dst, stride = d.img3.Cr[8*(by*d.img3.CStride+bx):], d.img3.CStride
- case 3:
- dst, stride = d.blackPix[8*(by*d.blackStride+bx):], d.blackStride
- 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)
- }
+ if err := d.reconstructBlock(&b, bx, by, int(compIndex)); err != nil {
+ return err
}
} // for j
} // for i
@@ -470,3 +433,70 @@ func (d *decoder) refineNonZeroes(b *block, zig, zigEnd, nz, delta int32) (int32
}
return zig, nil
}
+
+func (d *decoder) reconstructProgressiveImage() error {
+ // The h0, mxx, by and bx variables have the same meaning as in the
+ // processSOS method.
+ h0 := d.comp[0].h
+ mxx := (d.width + 8*h0 - 1) / (8 * h0)
+ for i := 0; i < d.nComp; i++ {
+ if d.progCoeffs[i] == nil {
+ continue
+ }
+ v := 8 * d.comp[0].v / d.comp[i].v
+ h := 8 * d.comp[0].h / d.comp[i].h
+ stride := mxx * d.comp[i].h
+ for by := 0; by*v < d.height; by++ {
+ for bx := 0; bx*h < d.width; bx++ {
+ if err := d.reconstructBlock(&d.progCoeffs[i][by*stride+bx], bx, by, i); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// reconstructBlock dequantizes, performs the inverse DCT and stores the block
+// to the image.
+func (d *decoder) reconstructBlock(b *block, bx, by, compIndex int) error {
+ qt := &d.quant[d.comp[compIndex].tq]
+ for zig := 0; zig < blockSize; zig++ {
+ b[unzig[zig]] *= qt[zig]
+ }
+ idct(b)
+ dst, stride := []byte(nil), 0
+ if d.nComp == 1 {
+ dst, stride = d.img1.Pix[8*(by*d.img1.Stride+bx):], d.img1.Stride
+ } else {
+ switch compIndex {
+ case 0:
+ dst, stride = d.img3.Y[8*(by*d.img3.YStride+bx):], d.img3.YStride
+ case 1:
+ dst, stride = d.img3.Cb[8*(by*d.img3.CStride+bx):], d.img3.CStride
+ case 2:
+ dst, stride = d.img3.Cr[8*(by*d.img3.CStride+bx):], d.img3.CStride
+ case 3:
+ dst, stride = d.blackPix[8*(by*d.blackStride+bx):], d.blackStride
+ 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)
+ }
+ }
+ return nil
+}