Shannon–Fano Decompress
Shannon–Fano is data compression algorithm, which replaces each symbol with an alternate binary representation. Common symbols are represented by few bits and uncommon symbols are represented by many bits.
For Shannon–Fano Compress algorithm click here.
Private Const MAX_TREE_NODES As Integer = 511
Public Class BitStream
Public BytePointer As Byte()
Public BitPosition As UInteger
Public Index As UInteger
End Class
Public Structure Symbol
Public Sym As UInteger
Public Count As UInteger
Public Code As UInteger
Public Bits As UInteger
End Structure
Public Class TreeNode
Public ChildA As TreeNode
Public ChildB As TreeNode
Public Symbol As Integer
End Class
Private Shared Sub initBitStream(ByRef stream As BitStream, buffer As Byte())
stream.BytePointer = buffer
stream.BitPosition = 0
End Sub
Private Shared Function readBit(ByRef stream As BitStream) As UInteger
Dim buffer As Byte() = stream.BytePointer
Dim bit As UInteger = stream.BitPosition
Dim x As UInteger = CUInt(If(Convert.ToBoolean(buffer(stream.Index) And (1 << CInt(7 - bit))), 1, 0))
bit = (bit + 1) And 7
If Not Convert.ToBoolean(bit) Then
stream.Index += 1
End If
stream.BitPosition = bit
Return x
End Function
Private Shared Function read8Bits(ByRef stream As BitStream) As UInteger
Dim buffer As Byte() = stream.BytePointer
Dim bit As UInteger = stream.BitPosition
Dim x As UInteger = CUInt((buffer(stream.Index) << CInt(bit)) Or (buffer(stream.Index + 1) >> CInt(8 - bit)))
stream.Index += 1
Return x
End Function
Private Shared Function recoverTree(nodes As TreeNode(), ByRef stream As BitStream, ByRef nodeNumber As UInteger) As TreeNode
Dim thisNode As TreeNode
thisNode = nodes(nodeNumber)
nodeNumber = nodeNumber + 1
thisNode.Symbol = -1
thisNode.ChildA = Nothing
thisNode.ChildB = Nothing
If Convert.ToBoolean(readBit(stream)) Then
thisNode.Symbol = CInt(read8Bits(stream))
Return thisNode
End If
If Convert.ToBoolean(readBit(stream)) Then
thisNode.ChildA = recoverTree(nodes, stream, nodeNumber)
End If
If Convert.ToBoolean(readBit(stream)) Then
thisNode.ChildB = recoverTree(nodes, stream, nodeNumber)
End If
Return thisNode
End Function
Public Shared Sub Decompress(input As Byte(), output As Byte(), inputSize As UInteger, outputSize As UInteger)
Dim nodes As TreeNode() = New TreeNode(MAX_TREE_NODES - 1) {}
For counter As Integer = 0 To nodes.Length - 1
nodes(counter) = New TreeNode()
Next
Dim root As TreeNode, node As TreeNode
Dim stream As New BitStream()
Dim i As UInteger, nodeCount As UInteger
Dim buffer As Byte()
If inputSize < 1 Then
Return
End If
initBitStream(stream, input)
nodeCount = 0
root = recoverTree(nodes, stream, nodeCount)
buffer = output
For i = 0 To outputSize - 1
node = root
While node.Symbol < 0
If Convert.ToBoolean(readBit(stream)) Then
node = node.ChildB
Else
node = node.ChildA
End If
End While
buffer(i) = CByte(node.Symbol)
Next
End Sub
Example
Dim decompressedData As Byte() = New Byte(originalDataSize - 1) {}
Decompress(compressedData, decompressedData, CUInt(compressedDataSize), originalDataSize)