codec/mjpeg/jpeg.go: simplified writing of huffman tables by calculating n values in global vars

This commit is contained in:
Saxon 2020-01-07 14:36:15 +10:30
parent 7fb5ed00a2
commit 7fca2257a4
1 changed files with 29 additions and 23 deletions

View File

@ -94,6 +94,14 @@ var (
ErrNoFrameStart = errors.New("missing start of frame") ErrNoFrameStart = errors.New("missing start of frame")
) )
// n values required for huffman table generation.
var (
nDCLum = deriveN(bitsDCLum)
nDCChr = deriveN(bitsDCChr)
nACLum = deriveN(bitsACLum)
nACChr = deriveN(bitsACChr)
)
// Slices used in the creation of huffman tables. // Slices used in the creation of huffman tables.
var ( var (
bitsDCLum = []byte{0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} bitsDCLum = []byte{0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}
@ -291,7 +299,7 @@ func (c *Context) ParsePayload(p []byte, m bool) error {
return nil return nil
} }
// writeHeader writes a JPEG header to the writer w. // writeHeader writes a JPEG header to the writer slice p.
func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable []byte) int { func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable []byte) int {
width <<= 3 width <<= 3
height <<= 3 height <<= 3
@ -305,8 +313,7 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable
binary.BigEndian.PutUint16(p[idx+4:], jfifHeadLen) binary.BigEndian.PutUint16(p[idx+4:], jfifHeadLen)
idx += 6 idx += 6
copy(p[idx:], jfifLabel) idx += copy(p[idx:], jfifLabel)
idx += len(jfifLabel)
binary.BigEndian.PutUint16(p[idx:], jfifVer) binary.BigEndian.PutUint16(p[idx:], jfifVer)
p[idx+2] = jfifDensityUnit p[idx+2] = jfifDensityUnit
@ -336,7 +343,7 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable
p[idx] = byte(i) p[idx] = byte(i)
idx++ idx++
copy(p[idx:], qtable[64*i:(64*i)+64]) idx += copy(p[idx:], qtable[64*i:(64*i)+64])
} }
// Define huffman table. // Define huffman table.
@ -345,10 +352,10 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable
lenIdx := idx lenIdx := idx
binary.BigEndian.PutUint16(p[idx:], 0) binary.BigEndian.PutUint16(p[idx:], 0)
idx += 2 idx += 2
idx += writeHuffman(p[idx:], 0, 0, bitsDCLum, valDC) idx += writeHuffman(p[idx:], bitsDCLum, valDC, 0, nDCLum)
idx += writeHuffman(p[idx:], 0, 1, bitsDCChr, valDC) idx += writeHuffman(p[idx:], bitsDCChr, valDC, 1, nDCChr)
idx += writeHuffman(p[idx:], 1, 0, bitsACLum, valACLum) idx += writeHuffman(p[idx:], bitsACLum, valACLum, 1<<4, nACLum)
idx += writeHuffman(p[idx:], 1, 1, bitsACChr, valACChr) idx += writeHuffman(p[idx:], bitsACChr, valACChr, 1<<4|1, nACChr)
binary.BigEndian.PutUint16(p[lenIdx:], uint16(idx-lenIdx)) binary.BigEndian.PutUint16(p[lenIdx:], uint16(idx-lenIdx))
// Start of frame. // Start of frame.
@ -389,21 +396,11 @@ func writeHeader(p []byte, _type, width, height, nbqTab int, dri uint16, qtable
return idx return idx
} }
// writeHuffman write a JPEG huffman table to w. // writeHuffman write a JPEG huffman table to alice p.
func writeHuffman(p []byte, class, id int, bits, values []byte) int { func writeHuffman(p, bits, values []byte, prefix byte, n int) int {
idx := 0 p[0] = prefix
p[idx] = uint8(class<<4 | id) i := copy(p[1:], bits[1:17])
idx++ return copy(p[i+1:], values[0:n]) + i + 1
var n int
for i := 1; i <= 16; i++ {
n += int(bits[i])
}
idx += copy(p[idx:], bits[1:17])
idx += copy(p[idx:], values[0:n])
return idx
} }
// defaultQTable returns a default quantization table. // defaultQTable returns a default quantization table.
@ -443,3 +440,12 @@ func clip(v, min, max int) int {
func get24(p []byte) int { func get24(p []byte) int {
return int(p[0]<<16) | int(p[1]<<8) | int(p[2]) return int(p[0]<<16) | int(p[1]<<8) | int(p[2])
} }
// deriveN calculates n values required for huffman table generation.
func deriveN(bits []byte) int {
var n int
for i := 1; i <= 16; i++ {
n += int(bits[i])
}
return n
}