unipdf/internal/ccittfax/decoding_tree.go

83 lines
1.9 KiB
Go
Raw Normal View History

2019-02-15 19:27:44 +03:00
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package ccittfax
2019-02-04 19:37:28 +03:00
2019-02-15 19:27:44 +03:00
// 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.
2019-02-04 19:37:28 +03:00
type decodingTreeNode struct {
Val byte
RunLen *int
2019-02-15 19:27:44 +03:00
Code *code
2019-02-04 19:37:28 +03:00
Left *decodingTreeNode
Right *decodingTreeNode
}
2019-02-15 19:27:44 +03:00
// addNode adds the node to the decoding tree.
func addNode(root *decodingTreeNode, code code, bitPos int, runLen int) {
2019-02-04 19:37:28 +03:00
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)
}
}
}
2019-02-15 19:27:44 +03:00
// 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) {
2019-02-04 19:37:28 +03:00
if root == nil {
return nil, nil
}
if bitPos == 16 {
return root.RunLen, root.Code
}
2019-02-15 19:27:44 +03:00
val := bitFromUint16(codeNum, bitPos)
2019-02-04 19:37:28 +03:00
bitPos++
var runLenPtr *int
2019-02-15 19:27:44 +03:00
var codePtr *code
2019-02-04 19:37:28 +03:00
if val == 1 {
2019-02-15 19:27:44 +03:00
runLenPtr, codePtr = findRunLen(root.Right, codeNum, bitPos)
2019-02-04 19:37:28 +03:00
} else {
2019-02-15 19:27:44 +03:00
runLenPtr, codePtr = findRunLen(root.Left, codeNum, bitPos)
2019-02-04 19:37:28 +03:00
}
if runLenPtr == nil {
runLenPtr = root.RunLen
codePtr = root.Code
}
return runLenPtr, codePtr
2019-02-15 19:27:44 +03:00
}