]> Cypherpunks repositories - gostls13.git/commitdiff
image/jpeg: fix extended sequential Huffman table selector (Th).
authorNigel Tao <nigeltao@golang.org>
Thu, 27 Apr 2017 01:38:10 +0000 (11:38 +1000)
committerNigel Tao <nigeltao@golang.org>
Thu, 27 Apr 2017 03:48:40 +0000 (03:48 +0000)
Previously, the package did not distinguish between baseline and
extended sequential images. Both are non-progressive images, but the Th
range differs between the two, as per Annex B of
https://www.w3.org/Graphics/JPEG/itu-t81.pdf

Extended sequential images are often emitted by the Guetzli encoder.

Fixes #19913

Change-Id: I3d0f9e16d5d374ee1c65e3a8fb87519de61cff94
Reviewed-on: https://go-review.googlesource.com/41831
Reviewed-by: David Symonds <dsymonds@golang.org>
src/image/jpeg/huffman.go
src/image/jpeg/reader.go
src/image/jpeg/scan.go
src/image/jpeg/writer.go

index 4f8fe8eff324f0c9493f7988f152e40e57eec5fb..95aaf71e2f36cc2f52887d6facb6b144f1246c15 100644 (file)
@@ -101,7 +101,8 @@ func (d *decoder) processDHT(n int) error {
                        return FormatError("bad Tc value")
                }
                th := d.tmp[0] & 0x0f
-               if th > maxTh || !d.progressive && th > 1 {
+               // The baseline th <= 1 restriction is specified in table B.5.
+               if th > maxTh || (d.baseline && th > 1) {
                        return FormatError("bad Th value")
                }
                h := &d.huff[tc][th]
index c5834219a3e45363fc3944fbcf518a2fa96e43d3..a915e96a4cf4f4a61db27025a91079076fdac8f3 100644 (file)
@@ -48,7 +48,7 @@ const (
 )
 
 const (
-       sof0Marker = 0xc0 // Start Of Frame (Baseline).
+       sof0Marker = 0xc0 // Start Of Frame (Baseline Sequential).
        sof1Marker = 0xc1 // Start Of Frame (Extended Sequential).
        sof2Marker = 0xc2 // Start Of Frame (Progressive).
        dhtMarker  = 0xc4 // Define Huffman Table.
@@ -126,9 +126,17 @@ type decoder struct {
        blackPix    []byte
        blackStride int
 
-       ri                  int // Restart Interval.
-       nComp               int
-       progressive         bool
+       ri    int // Restart Interval.
+       nComp int
+
+       // As per section 4.5, there are four modes of operation (selected by the
+       // SOF? markers): sequential DCT, progressive DCT, lossless and
+       // hierarchical, although this implementation does not support the latter
+       // two non-DCT modes. Sequential DCT is further split into baseline and
+       // extended, as per section 4.11.
+       baseline    bool
+       progressive bool
+
        jfif                bool
        adobeTransformValid bool
        adobeTransform      uint8
@@ -596,6 +604,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
 
                switch marker {
                case sof0Marker, sof1Marker, sof2Marker:
+                       d.baseline = marker == sof0Marker
                        d.progressive = marker == sof2Marker
                        err = d.processSOF(n)
                        if configOnly && d.jfif {
index e1104d27c2342fa46a8fb89bbf42e66b7b7ab026..712e7e35ff886514899ac976a5141f320ccfeda5 100644 (file)
@@ -92,12 +92,13 @@ func (d *decoder) processSOS(n int) error {
                }
                totalHV += d.comp[compIndex].h * d.comp[compIndex].v
 
+               // The baseline t <= 1 restriction is specified in table B.3.
                scan[i].td = d.tmp[2+2*i] >> 4
-               if scan[i].td > maxTh {
+               if t := scan[i].td; t > maxTh || (d.baseline && t > 1) {
                        return FormatError("bad Td value")
                }
                scan[i].ta = d.tmp[2+2*i] & 0x0f
-               if scan[i].ta > maxTh {
+               if t := scan[i].ta; t > maxTh || (d.baseline && t > 1) {
                        return FormatError("bad Ta value")
                }
        }
@@ -122,7 +123,8 @@ func (d *decoder) processSOS(n int) error {
        // 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.
+       // For sequential JPEGs, these parameters are hard-coded to 0/63/0/0, as
+       // per table B.3.
        zigStart, zigEnd, ah, al := int32(0), int32(blockSize-1), uint32(0), uint32(0)
        if d.progressive {
                zigStart = int32(d.tmp[1+2*nComp])
@@ -177,7 +179,7 @@ func (d *decoder) processSOS(n int) error {
                                        // 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:
+                                       // For a sequential 32x16 pixel image, the Y blocks visiting order is:
                                        //      0 1 4 5
                                        //      2 3 6 7
                                        //
index ce7728b484cc53f092d36e120974d3d1d585130c..a600499004725f93bcc99d3b8f6700672e291b7c 100644 (file)
@@ -311,7 +311,7 @@ func (e *encoder) writeDQT() {
        }
 }
 
-// writeSOF0 writes the Start Of Frame (Baseline) marker.
+// writeSOF0 writes the Start Of Frame (Baseline Sequential) marker.
 func (e *encoder) writeSOF0(size image.Point, nComponent int) {
        markerlen := 8 + 3*nComponent
        e.writeMarkerHeader(sof0Marker, markerlen)