mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-30 13:48:51 +08:00
713 lines
15 KiB
Go
713 lines
15 KiB
Go
package ccittfaxdecode
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
)
|
|
|
|
var (
|
|
ErrEOFBCorrupt = errors.New("EOFB code is corrupted")
|
|
ErrRTCCorrupt = errors.New("RTC code is corrupted")
|
|
ErrWrongCodeInHorizontalMode = errors.New("wrong code in horizontal mode")
|
|
ErrNoEOLFound = errors.New("no EOL found while the EndOfLine parameter is true")
|
|
ErrInvalidEOL = errors.New("invalid EOL")
|
|
ErrInvalid2DCode = errors.New("invalid 2D code")
|
|
|
|
whiteTree = &decodingTreeNode{
|
|
Val: 255,
|
|
}
|
|
blackTree = &decodingTreeNode{
|
|
Val: 255,
|
|
}
|
|
twoDimTree = &decodingTreeNode{
|
|
Val: 255,
|
|
}
|
|
)
|
|
|
|
func init() {
|
|
for runLen, code := range WTerms {
|
|
addNode(whiteTree, code, 0, runLen)
|
|
}
|
|
|
|
for runLen, code := range WMakeups {
|
|
addNode(whiteTree, code, 0, runLen)
|
|
}
|
|
|
|
for runLen, code := range BTerms {
|
|
addNode(blackTree, code, 0, runLen)
|
|
}
|
|
|
|
for runLen, code := range BMakeups {
|
|
addNode(blackTree, code, 0, runLen)
|
|
}
|
|
|
|
for runLen, code := range CommonMakeups {
|
|
addNode(whiteTree, code, 0, runLen)
|
|
addNode(blackTree, code, 0, runLen)
|
|
}
|
|
|
|
addNode(twoDimTree, P, 0, 0)
|
|
addNode(twoDimTree, H, 0, 0)
|
|
addNode(twoDimTree, V0, 0, 0)
|
|
addNode(twoDimTree, V1R, 0, 0)
|
|
addNode(twoDimTree, V2R, 0, 0)
|
|
addNode(twoDimTree, V3R, 0, 0)
|
|
addNode(twoDimTree, V1L, 0, 0)
|
|
addNode(twoDimTree, V2L, 0, 0)
|
|
addNode(twoDimTree, V3L, 0, 0)
|
|
}
|
|
|
|
func (e *Encoder) Decode(encoded []byte) ([][]byte, error) {
|
|
if e.BlackIs1 {
|
|
white = 0
|
|
black = 1
|
|
} else {
|
|
white = 1
|
|
black = 0
|
|
}
|
|
|
|
if e.K == 0 {
|
|
return e.decodeG31D(encoded)
|
|
}
|
|
|
|
if e.K > 0 {
|
|
return e.decodeG32D(encoded)
|
|
}
|
|
|
|
if e.K < 4 {
|
|
return e.decodeG4(encoded)
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (e *Encoder) decodeG31D(encoded []byte) ([][]byte, error) {
|
|
var pixels [][]byte
|
|
|
|
// do g31d decoding
|
|
var bitPos int
|
|
for (bitPos / 8) < len(encoded) {
|
|
var gotEOL bool
|
|
|
|
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
|
if !gotEOL {
|
|
if e.EndOfLine {
|
|
return nil, ErrNoEOLFound
|
|
}
|
|
} else {
|
|
// 5 EOLs left to fill RTC
|
|
for i := 0; i < 5; i++ {
|
|
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
|
|
|
if !gotEOL {
|
|
if i == 0 {
|
|
break
|
|
}
|
|
|
|
return nil, ErrInvalidEOL
|
|
}
|
|
}
|
|
|
|
// got RTC
|
|
if gotEOL {
|
|
break
|
|
}
|
|
}
|
|
|
|
var row []byte
|
|
row, bitPos = e.decodeRow1D(encoded, bitPos)
|
|
|
|
if e.EncodedByteAlign && bitPos%8 != 0 {
|
|
bitPos += 8 - bitPos%8
|
|
}
|
|
|
|
pixels = append(pixels, row)
|
|
|
|
if e.Rows > 0 && !e.EndOfBlock && len(pixels) >= e.Rows {
|
|
break
|
|
}
|
|
}
|
|
|
|
return pixels, nil
|
|
}
|
|
|
|
func (e *Encoder) decodeG32D(encoded []byte) ([][]byte, error) {
|
|
var (
|
|
pixels [][]byte
|
|
bitPos int
|
|
err error
|
|
)
|
|
byteLoop:
|
|
for (bitPos / 8) < len(encoded) {
|
|
var gotEOL bool
|
|
gotEOL, bitPos, err = tryFetchRTC2D(encoded, bitPos)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if gotEOL {
|
|
break
|
|
}
|
|
|
|
gotEOL, bitPos = tryFetchEOL1(encoded, bitPos)
|
|
|
|
if !gotEOL {
|
|
if e.EndOfLine {
|
|
return nil, ErrNoEOLFound
|
|
}
|
|
}
|
|
|
|
// decode 1 of K rows as 1D
|
|
var row []byte
|
|
row, bitPos = e.decodeRow1D(encoded, bitPos)
|
|
|
|
if e.EncodedByteAlign && bitPos%8 != 0 {
|
|
bitPos += 8 - bitPos%8
|
|
}
|
|
|
|
if row != nil {
|
|
pixels = append(pixels, row)
|
|
}
|
|
|
|
if e.Rows > 0 && !e.EndOfBlock && len(pixels) >= e.Rows {
|
|
break
|
|
}
|
|
|
|
// decode K-1 rows as 2D
|
|
for i := 1; i < e.K && (bitPos/8) < len(encoded); i++ {
|
|
gotEOL, bitPos = tryFetchEOL0(encoded, bitPos)
|
|
if !gotEOL {
|
|
gotEOL, bitPos, err = tryFetchRTC2D(encoded, bitPos)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if gotEOL {
|
|
break byteLoop
|
|
} else {
|
|
if e.EndOfLine {
|
|
return nil, ErrNoEOLFound
|
|
}
|
|
}
|
|
}
|
|
|
|
var (
|
|
twoDimCode Code
|
|
ok bool
|
|
)
|
|
|
|
isWhite := true
|
|
var pixelsRow []byte
|
|
a0 := -1
|
|
for twoDimCode, bitPos, ok = fetchNext2DCode(encoded, bitPos); ok; twoDimCode, bitPos, ok = fetchNext2DCode(encoded, bitPos) {
|
|
switch twoDimCode {
|
|
case P:
|
|
// do pass mode decoding
|
|
pixelsRow, a0 = decodePassMode(pixels, pixelsRow, isWhite, a0)
|
|
case H:
|
|
// do horizontal mode decoding
|
|
pixelsRow, bitPos, a0, err = decodeHorizontalMode(encoded, pixelsRow, bitPos, isWhite, a0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case V0:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
|
|
|
isWhite = !isWhite
|
|
case V1R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
|
|
|
isWhite = !isWhite
|
|
case V2R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
|
|
|
isWhite = !isWhite
|
|
case V3R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
|
|
|
isWhite = !isWhite
|
|
case V1L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
|
|
|
isWhite = !isWhite
|
|
case V2L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
|
|
|
isWhite = !isWhite
|
|
case V3L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
|
|
|
isWhite = !isWhite
|
|
}
|
|
|
|
// TODO: additionally check for errors. EOL should be fetched when a0 == len(pixels[len(pixels)-1])
|
|
if len(pixelsRow) >= e.Columns {
|
|
break
|
|
}
|
|
}
|
|
|
|
if e.EncodedByteAlign && bitPos%8 != 0 {
|
|
bitPos += 8 - bitPos%8
|
|
}
|
|
|
|
if pixelsRow != nil {
|
|
pixels = append(pixels, pixelsRow)
|
|
}
|
|
|
|
if e.Rows > 0 && !e.EndOfBlock && len(pixels) >= e.Rows {
|
|
break byteLoop
|
|
}
|
|
}
|
|
}
|
|
|
|
return pixels, nil
|
|
}
|
|
|
|
func (e *Encoder) decodeG4(encoded []byte) ([][]byte, error) {
|
|
whiteReferenceLine := make([]byte, e.Columns)
|
|
for i := range whiteReferenceLine {
|
|
whiteReferenceLine[i] = white
|
|
}
|
|
|
|
pixels := make([][]byte, 1)
|
|
pixels[0] = whiteReferenceLine
|
|
|
|
var (
|
|
gotEOL bool
|
|
err error
|
|
bitPos int
|
|
)
|
|
for (bitPos / 8) < len(encoded) {
|
|
if len(pixels) == 1198 {
|
|
log.Println()
|
|
}
|
|
// try get EOFB
|
|
gotEOL, bitPos, err = tryFetchEOFB(encoded, bitPos)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if gotEOL {
|
|
break
|
|
}
|
|
|
|
var (
|
|
twoDimCode Code
|
|
ok bool
|
|
)
|
|
|
|
isWhite := true
|
|
var pixelsRow []byte
|
|
a0 := -1
|
|
for a0 < e.Columns {
|
|
twoDimCode, bitPos, ok = fetchNext2DCode(encoded, bitPos)
|
|
if !ok {
|
|
return nil, ErrInvalid2DCode
|
|
}
|
|
|
|
switch twoDimCode {
|
|
case P:
|
|
// do pass mode decoding
|
|
pixelsRow, a0 = decodePassMode(pixels, pixelsRow, isWhite, a0)
|
|
case H:
|
|
// do horizontal mode decoding
|
|
pixelsRow, bitPos, a0, err = decodeHorizontalMode(encoded, pixelsRow, bitPos, isWhite, a0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
case V0:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
|
|
|
isWhite = !isWhite
|
|
case V1R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
|
|
|
isWhite = !isWhite
|
|
case V2R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
|
|
|
isWhite = !isWhite
|
|
case V3R:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
|
|
|
isWhite = !isWhite
|
|
case V1L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
|
|
|
isWhite = !isWhite
|
|
case V2L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
|
|
|
isWhite = !isWhite
|
|
case V3L:
|
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
|
|
|
isWhite = !isWhite
|
|
}
|
|
|
|
if len(pixelsRow) >= e.Columns {
|
|
break
|
|
}
|
|
}
|
|
|
|
if e.EncodedByteAlign && bitPos%8 != 0 {
|
|
bitPos += 8 - bitPos%8
|
|
}
|
|
|
|
pixels = append(pixels, pixelsRow)
|
|
|
|
if e.Rows > 0 && !e.EndOfBlock && len(pixels) >= e.Rows {
|
|
break
|
|
}
|
|
}
|
|
|
|
pixels = pixels[1:]
|
|
|
|
return pixels, nil
|
|
}
|
|
|
|
func decodeVerticalMode(pixels [][]byte, pixelsRow []byte, isWhite bool, a0, shift int) ([]byte, int) {
|
|
b1 := seekB12D(pixelsRow, pixels[len(pixels)-1], a0, isWhite)
|
|
// true for V0
|
|
a1 := b1 + shift
|
|
|
|
if a0 == -1 {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, a1-a0-1)
|
|
} else {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, a1-a0)
|
|
}
|
|
|
|
a0 = a1
|
|
|
|
return pixelsRow, a0
|
|
}
|
|
|
|
func decodePassMode(pixels [][]byte, pixelsRow []byte, isWhite bool, a0 int) ([]byte, int) {
|
|
b1 := seekB12D(pixelsRow, pixels[len(pixels)-1], a0, isWhite)
|
|
b2 := seekChangingElem(pixels[len(pixels)-1], b1)
|
|
|
|
if a0 == -1 {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, b2-a0-1)
|
|
} else {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, b2-a0)
|
|
}
|
|
|
|
a0 = b2
|
|
|
|
return pixelsRow, a0
|
|
}
|
|
|
|
func decodeHorizontalMode(encoded, pixelsRow []byte, bitPos int, isWhite bool, a0 int) ([]byte, int, int, error) {
|
|
startingBitPos := bitPos
|
|
|
|
var err error
|
|
pixelsRow, bitPos, err = decodeNextRunLen(encoded, pixelsRow, bitPos, isWhite)
|
|
if err != nil {
|
|
return pixelsRow, startingBitPos, a0, err
|
|
}
|
|
|
|
isWhite = !isWhite
|
|
|
|
pixelsRow, bitPos, err = decodeNextRunLen(encoded, pixelsRow, bitPos, isWhite)
|
|
if err != nil {
|
|
return pixelsRow, startingBitPos, a0, err
|
|
}
|
|
|
|
// the last code was the code of a1a2 run. a0 was moved to a2
|
|
// while encoding. that's why we put a0 on the a2 and continue
|
|
a0 = len(pixelsRow)
|
|
|
|
return pixelsRow, bitPos, a0, nil
|
|
}
|
|
|
|
func decodeNextRunLen(encoded, pixelsRow []byte, bitPos int, isWhite bool) ([]byte, int, error) {
|
|
startingBitPos := bitPos
|
|
|
|
var runLen int
|
|
|
|
for runLen, bitPos = fetchNextRunLen(encoded, bitPos, isWhite); runLen != -1; runLen, bitPos = fetchNextRunLen(encoded, bitPos, isWhite) {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, runLen)
|
|
|
|
// got terminal code, switch color
|
|
if runLen < 64 {
|
|
break
|
|
}
|
|
}
|
|
|
|
if runLen == -1 {
|
|
return pixelsRow, startingBitPos, ErrWrongCodeInHorizontalMode
|
|
}
|
|
|
|
return pixelsRow, bitPos, nil
|
|
}
|
|
|
|
func tryFetchRTC2D(encoded []byte, bitPos int) (bool, int, error) {
|
|
startingBitPos := bitPos
|
|
var gotEOL = false
|
|
|
|
// 6 EOL1s to fill RTC
|
|
for i := 0; i < 6; i++ {
|
|
gotEOL, bitPos = tryFetchEOL1(encoded, bitPos)
|
|
|
|
if !gotEOL {
|
|
if i > 1 {
|
|
return false, startingBitPos, ErrRTCCorrupt
|
|
} else {
|
|
bitPos = startingBitPos
|
|
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return gotEOL, bitPos, nil
|
|
}
|
|
|
|
func tryFetchEOFB(encoded []byte, bitPos int) (bool, int, error) {
|
|
startingBitPos := bitPos
|
|
|
|
var gotEOL bool
|
|
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
|
if gotEOL {
|
|
// 1 EOL to fill EOFB
|
|
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
|
|
|
if gotEOL {
|
|
return true, bitPos, nil
|
|
} else {
|
|
return false, startingBitPos, ErrEOFBCorrupt
|
|
}
|
|
}
|
|
|
|
return false, startingBitPos, nil
|
|
}
|
|
|
|
func bitFromUint16(num uint16, bitPos int) byte {
|
|
if bitPos < 8 {
|
|
num >>= 8
|
|
}
|
|
|
|
bitPos %= 8
|
|
|
|
mask := byte(0x01 << (7 - uint(bitPos)))
|
|
|
|
return (byte(num) & mask) >> (7 - uint(bitPos))
|
|
}
|
|
|
|
func fetchNextRunLen(data []byte, bitPos int, isWhite bool) (int, int) {
|
|
var (
|
|
codeNum uint16
|
|
codeBitPos int
|
|
startingBitPos int
|
|
)
|
|
|
|
startingBitPos = bitPos
|
|
codeNum, codeBitPos, bitPos = fetchNextCode(data, bitPos)
|
|
|
|
runLen, code := decodeRunLenFromUint16(codeNum, codeBitPos, isWhite)
|
|
if runLen == -1 {
|
|
return -1, startingBitPos
|
|
}
|
|
|
|
return runLen, startingBitPos + code.BitsWritten
|
|
}
|
|
|
|
func fetchNext2DCode(data []byte, bitPos int) (Code, int, bool) {
|
|
var (
|
|
codeNum uint16
|
|
codeBitPos int
|
|
startingBitPos int
|
|
)
|
|
|
|
startingBitPos = bitPos
|
|
codeNum, codeBitPos, bitPos = fetchNextCode(data, bitPos)
|
|
|
|
code, ok := get2DCodeFromUint16(codeNum, codeBitPos)
|
|
if !ok {
|
|
return Code{}, startingBitPos, false
|
|
}
|
|
|
|
return code, startingBitPos + code.BitsWritten, true
|
|
}
|
|
|
|
func get2DCodeFromUint16(encoded uint16, bitPos int) (Code, bool) {
|
|
_, codePtr := findRunLen(twoDimTree, encoded, bitPos)
|
|
|
|
if codePtr == nil {
|
|
return Code{}, false
|
|
}
|
|
|
|
return *codePtr, true
|
|
}
|
|
|
|
func decodeRunLenFromUint16(encoded uint16, bitPos int, isWhite bool) (int, Code) {
|
|
var runLenPtr *int
|
|
var codePtr *Code
|
|
|
|
if isWhite {
|
|
runLenPtr, codePtr = findRunLen(whiteTree, encoded, bitPos)
|
|
} else {
|
|
runLenPtr, codePtr = findRunLen(blackTree, encoded, bitPos)
|
|
}
|
|
|
|
if runLenPtr == nil {
|
|
return -1, Code{}
|
|
}
|
|
|
|
return *runLenPtr, *codePtr
|
|
}
|
|
|
|
func fetchNextCode(data []byte, bitPos int) (uint16, int, int) {
|
|
startingBitPos := bitPos
|
|
|
|
bytePos := bitPos / 8
|
|
bitPos %= 8
|
|
|
|
if bytePos >= len(data) {
|
|
return 0, 16, startingBitPos
|
|
}
|
|
|
|
// take the rest bits from the current byte
|
|
mask := byte(0xFF >> uint(bitPos))
|
|
code := uint16((data[bytePos]&mask)<<uint(bitPos)) << 8
|
|
|
|
bitsWritten := 8 - bitPos
|
|
|
|
bytePos++
|
|
bitPos = 0
|
|
|
|
if bytePos >= len(data) {
|
|
return code >> (16 - uint(bitsWritten)), 16 - bitsWritten, startingBitPos + bitsWritten
|
|
}
|
|
|
|
// take the whole next byte
|
|
code |= uint16(data[bytePos]) << (8 - uint(bitsWritten))
|
|
|
|
bitsWritten += 8
|
|
|
|
bytePos++
|
|
bitPos = 0
|
|
|
|
if bytePos >= len(data) {
|
|
return code >> (16 - uint(bitsWritten)), 16 - bitsWritten, startingBitPos + bitsWritten
|
|
}
|
|
|
|
if bitsWritten == 16 {
|
|
return code, 0, startingBitPos + bitsWritten
|
|
}
|
|
|
|
// take the needed bits from the next byte
|
|
leftToWrite := 16 - bitsWritten
|
|
|
|
code |= uint16(data[bytePos] >> (8 - uint(leftToWrite)))
|
|
|
|
return code, 0, startingBitPos + 16
|
|
}
|
|
|
|
func (e *Encoder) decodeRow1D(encoded []byte, bitPos int) ([]byte, int) {
|
|
var pixelsRow []byte
|
|
|
|
isWhite := true
|
|
|
|
var runLen int
|
|
runLen, bitPos = fetchNextRunLen(encoded, bitPos, isWhite)
|
|
for runLen != -1 {
|
|
pixelsRow = drawPixels(pixelsRow, isWhite, runLen)
|
|
|
|
// got terminal code, switch color
|
|
if runLen < 64 {
|
|
if len(pixelsRow) >= e.Columns {
|
|
break
|
|
}
|
|
|
|
isWhite = !isWhite
|
|
}
|
|
|
|
runLen, bitPos = fetchNextRunLen(encoded, bitPos, isWhite)
|
|
}
|
|
|
|
return pixelsRow, bitPos
|
|
}
|
|
|
|
func drawPixels(row []byte, isWhite bool, length int) []byte {
|
|
if length < 0 {
|
|
return row
|
|
}
|
|
|
|
runLenPixels := make([]byte, length)
|
|
if isWhite {
|
|
for i := 0; i < len(runLenPixels); i++ {
|
|
runLenPixels[i] = white
|
|
}
|
|
} else {
|
|
for i := 0; i < len(runLenPixels); i++ {
|
|
runLenPixels[i] = black
|
|
}
|
|
}
|
|
|
|
row = append(row, runLenPixels...)
|
|
|
|
return row
|
|
}
|
|
|
|
func tryFetchEOL(encoded []byte, bitPos int) (bool, int) {
|
|
startingBitPos := bitPos
|
|
|
|
var (
|
|
code uint16
|
|
codeBitPos int
|
|
)
|
|
|
|
code, codeBitPos, bitPos = fetchNextCode(encoded, bitPos)
|
|
|
|
// when this is true, the fetched code if less than 12 bits long,
|
|
// which doesn't fit the EOL code length
|
|
if codeBitPos > 4 {
|
|
return false, startingBitPos
|
|
}
|
|
|
|
// format the fetched code
|
|
code >>= uint(4 - codeBitPos)
|
|
code <<= 4
|
|
|
|
if code != EOL.Code {
|
|
return false, startingBitPos
|
|
} else {
|
|
return true, bitPos - 4 + codeBitPos
|
|
}
|
|
}
|
|
|
|
func tryFetchExtendedEOL(encoded []byte, bitPos int, eolCode Code) (bool, int) {
|
|
startingBitPos := bitPos
|
|
|
|
var (
|
|
code uint16
|
|
codeBitPos int
|
|
)
|
|
|
|
code, codeBitPos, bitPos = fetchNextCode(encoded, bitPos)
|
|
|
|
// when this is true, the fetched code if less than 13 bits long,
|
|
// which doesn't fit the EOL0/EOL1 code length
|
|
if codeBitPos > 3 {
|
|
return false, startingBitPos
|
|
}
|
|
|
|
// format the fetched code
|
|
code >>= uint(3 - codeBitPos)
|
|
code <<= 3
|
|
|
|
if code != eolCode.Code {
|
|
return false, startingBitPos
|
|
} else {
|
|
return true, bitPos - 3 + codeBitPos
|
|
}
|
|
}
|
|
|
|
func tryFetchEOL0(encoded []byte, bitPos int) (bool, int) {
|
|
return tryFetchExtendedEOL(encoded, bitPos, EOL0)
|
|
}
|
|
|
|
func tryFetchEOL1(encoded []byte, bitPos int) (bool, int) {
|
|
return tryFetchExtendedEOL(encoded, bitPos, EOL1)
|
|
}
|