mirror of
https://github.com/golang/go
synced 2024-11-23 18:20:04 -07:00
image/jpeg: fix extended sequential Huffman table selector (Th).
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>
This commit is contained in:
parent
6664ccb453
commit
35cbc3b55b
@ -101,7 +101,8 @@ func (d *decoder) processDHT(n int) error {
|
|||||||
return FormatError("bad Tc value")
|
return FormatError("bad Tc value")
|
||||||
}
|
}
|
||||||
th := d.tmp[0] & 0x0f
|
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")
|
return FormatError("bad Th value")
|
||||||
}
|
}
|
||||||
h := &d.huff[tc][th]
|
h := &d.huff[tc][th]
|
||||||
|
@ -48,7 +48,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
sof0Marker = 0xc0 // Start Of Frame (Baseline).
|
sof0Marker = 0xc0 // Start Of Frame (Baseline Sequential).
|
||||||
sof1Marker = 0xc1 // Start Of Frame (Extended Sequential).
|
sof1Marker = 0xc1 // Start Of Frame (Extended Sequential).
|
||||||
sof2Marker = 0xc2 // Start Of Frame (Progressive).
|
sof2Marker = 0xc2 // Start Of Frame (Progressive).
|
||||||
dhtMarker = 0xc4 // Define Huffman Table.
|
dhtMarker = 0xc4 // Define Huffman Table.
|
||||||
@ -126,9 +126,17 @@ type decoder struct {
|
|||||||
blackPix []byte
|
blackPix []byte
|
||||||
blackStride int
|
blackStride int
|
||||||
|
|
||||||
ri int // Restart Interval.
|
ri int // Restart Interval.
|
||||||
nComp int
|
nComp int
|
||||||
progressive bool
|
|
||||||
|
// 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
|
jfif bool
|
||||||
adobeTransformValid bool
|
adobeTransformValid bool
|
||||||
adobeTransform uint8
|
adobeTransform uint8
|
||||||
@ -596,6 +604,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
|
|||||||
|
|
||||||
switch marker {
|
switch marker {
|
||||||
case sof0Marker, sof1Marker, sof2Marker:
|
case sof0Marker, sof1Marker, sof2Marker:
|
||||||
|
d.baseline = marker == sof0Marker
|
||||||
d.progressive = marker == sof2Marker
|
d.progressive = marker == sof2Marker
|
||||||
err = d.processSOF(n)
|
err = d.processSOF(n)
|
||||||
if configOnly && d.jfif {
|
if configOnly && d.jfif {
|
||||||
|
@ -92,12 +92,13 @@ func (d *decoder) processSOS(n int) error {
|
|||||||
}
|
}
|
||||||
totalHV += d.comp[compIndex].h * d.comp[compIndex].v
|
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
|
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")
|
return FormatError("bad Td value")
|
||||||
}
|
}
|
||||||
scan[i].ta = d.tmp[2+2*i] & 0x0f
|
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")
|
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
|
// by the second-least significant bit, followed by the least
|
||||||
// significant bit.
|
// 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)
|
zigStart, zigEnd, ah, al := int32(0), int32(blockSize-1), uint32(0), uint32(0)
|
||||||
if d.progressive {
|
if d.progressive {
|
||||||
zigStart = int32(d.tmp[1+2*nComp])
|
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
|
// 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.
|
// 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
|
// 0 1 4 5
|
||||||
// 2 3 6 7
|
// 2 3 6 7
|
||||||
//
|
//
|
||||||
|
@ -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) {
|
func (e *encoder) writeSOF0(size image.Point, nComponent int) {
|
||||||
markerlen := 8 + 3*nComponent
|
markerlen := 8 + 3*nComponent
|
||||||
e.writeMarkerHeader(sof0Marker, markerlen)
|
e.writeMarkerHeader(sof0Marker, markerlen)
|
||||||
|
Loading…
Reference in New Issue
Block a user