unipdf/internal/ccittfax/decoding_tree.go
2019-05-16 20:44:51 +00:00

83 lines
1.9 KiB
Go

/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package ccittfax
// decodingTreeNode is a node of a tree which represents the finite state machine for
// searching the decoded pixel run lengths having the bit sequence. `Val` is a single bit
// in a byte value. It is used to navigate the tree. Each node either contains a decoded
// run length and the corresponding code or not.
type decodingTreeNode struct {
Val byte
RunLen *int
Code *code
Left *decodingTreeNode
Right *decodingTreeNode
}
// addNode adds the node to the decoding tree.
func addNode(root *decodingTreeNode, code code, bitPos int, runLen int) {
val := bitFromUint16(code.Code, bitPos)
bitPos++
if val == 1 {
if root.Right == nil {
root.Right = &decodingTreeNode{
Val: val,
}
}
if bitPos == code.BitsWritten {
root.Right.RunLen = &runLen
root.Right.Code = &code
} else {
addNode(root.Right, code, bitPos, runLen)
}
} else {
if root.Left == nil {
root.Left = &decodingTreeNode{
Val: val,
}
}
if bitPos == code.BitsWritten {
root.Left.RunLen = &runLen
root.Left.Code = &code
} else {
addNode(root.Left, code, bitPos, runLen)
}
}
}
// findRunLen searches for the decoded pixel run length and the corresponding code
// having the bit sequence represented as a single uint16 value.
func findRunLen(root *decodingTreeNode, codeNum uint16, bitPos int) (*int, *code) {
if root == nil {
return nil, nil
}
if bitPos == 16 {
return root.RunLen, root.Code
}
val := bitFromUint16(codeNum, bitPos)
bitPos++
var runLenPtr *int
var codePtr *code
if val == 1 {
runLenPtr, codePtr = findRunLen(root.Right, codeNum, bitPos)
} else {
runLenPtr, codePtr = findRunLen(root.Left, codeNum, bitPos)
}
if runLenPtr == nil {
runLenPtr = root.RunLen
codePtr = root.Code
}
return runLenPtr, codePtr
}