public AccumulatedProbabilityCounts(Int32ProbabilityContexts int32ProbabilityContexts) { //this.int32ProbabilityContexts = int32ProbabilityContexts; SymbolCounts = new Int32[int32ProbabilityContexts.ProbabilityContextTableEntries.Length]; EntriesByAccumulatedCountPerContext = new SortedDictionary <int, int> [SymbolCounts.Length]; for (int tableIndex = 0, tableCount = SymbolCounts.Length; tableIndex < tableCount; ++tableIndex) { var table = int32ProbabilityContexts.ProbabilityContextTableEntries[tableIndex]; int accumulatedCount = 0; var entryByAccumulatedCountPerContext = new SortedDictionary <int, int>(); EntriesByAccumulatedCountPerContext[tableIndex] = entryByAccumulatedCountPerContext; for (int tableEntryIndex = 0, tableEntryCount = table.Length; tableEntryIndex < tableEntryCount; ++tableEntryIndex) { accumulatedCount += table[tableEntryIndex].OccurrenceCount; entryByAccumulatedCountPerContext[accumulatedCount - 1] = tableEntryIndex; } SymbolCounts[tableIndex] = accumulatedCount; } }
private static int[] DecodeBytes(Stream stream) { var codecType = (CODECType)StreamUtils.ReadByte(stream); Int32ProbabilityContexts int32ProbabilityContexts = null; //int outOfBandValueCount; //int[] outOfBandValues; if (codecType == CODECType.Huffman || codecType == CODECType.Arithmetic) { throw new NotImplementedException("Huffman && Arithmetic codec NOT IMPLEMENTED"); /*int32ProbabilityContexts = new Int32ProbabilityContexts(stream); * outOfBandValueCount = StreamUtils.ReadInt32(stream); * * if (outOfBandValueCount > 0) * { * outOfBandValues = DecodeBytes(stream); * }*/ } if (codecType != CODECType.Null) { var codeTextLength = StreamUtils.ReadInt32(stream); var valueElementCount = StreamUtils.ReadInt32(stream); //var symbolCount = valueElementCount; if (int32ProbabilityContexts != null && int32ProbabilityContexts.ProbabilityContextTableEntries.Length > 1) { StreamUtils.ReadInt32(stream); //symbolCount } var wordsToRead = StreamUtils.ReadInt32(stream); var codeText = new uint[wordsToRead]; for (int i = 0; i < wordsToRead; ++i) { UInt32 codeTextWord; if (StreamUtils.DataIsLittleEndian) // Convert to BigEndian { var bytes = StreamUtils.ReadBytes(stream, 4, true); Array.Reverse(bytes); /*var result = new UInt32[1]; * Buffer.BlockCopy(bytes, 0, result, 0, 4); * * codeTextWord = result[0];*/ codeTextWord = Convert.FromBytes <UInt32>(bytes); } else { codeTextWord = StreamUtils.ReadUInt32(stream); } codeText[i] = codeTextWord; } switch (codecType) { case CODECType.Bitlength: return(BitlengthCoder.Decode(codeText, valueElementCount, codeTextLength)); case CODECType.Huffman: throw new NotImplementedException("Huffman codec NOT IMPLEMENTED"); case CODECType.Arithmetic: throw new NotImplementedException("Huffman codec NOT IMPLEMENTED"); } } else { var integersToRead = StreamUtils.ReadInt32(stream); var decodedSymbols = new int[integersToRead]; for (int i = 0; i < integersToRead; ++i) { decodedSymbols[i] = StreamUtils.ReadInt32(stream); } return(decodedSymbols); } return(new int[0]); }
public static Int32[] Decode(UInt32[] codeTextWords, Int32ProbabilityContexts int32ProbabilityContexts, Int32[] outOfBandValues, Int32 valueCount) { var bytes = new Byte[codeTextWords.Length * 4]; Buffer.BlockCopy(codeTextWords, 0, bytes, 0, bytes.Length); var decodedSymbols = new List <Int32>(valueCount); var accumulatedProbabilityCounts = new AccumulatedProbabilityCounts(int32ProbabilityContexts); var code = 0x0000; var low = 0x0000; var high = 0xffff; var bitBuffer = 0; var bits = 0; var symbolCount = valueCount; var currentContext = 0; var newSymbolRange = new Int32[3]; var outOfBandDataCounter = 0; using (var memoryStream = new MemoryStream(bytes)) { var bitStream = new BitStream(memoryStream); GetNextCodeText(bitStream, out bitBuffer, out bits); code = (bitBuffer >> 16) & 0xffff; bitBuffer <<= 16; bits = 16; for (int i = 0; i < symbolCount; ++i) { var rescaledCode = (((code - low) + 1) * accumulatedProbabilityCounts.SymbolCounts[currentContext] - 1) / ((high - low) + 1); var int32ProbabilityContextTableEntry = GetEntryAndSymbolRangeByRescaledCode(accumulatedProbabilityCounts, int32ProbabilityContexts, currentContext, rescaledCode, ref newSymbolRange); var range = high - low + 1; high = low + ((range * newSymbolRange[1]) / newSymbolRange[2] - 1); low += ((range * newSymbolRange[0]) / newSymbolRange[2]); while (true) { if (((~(high ^ low)) & 0x8000) > 0) { //Shift both out if most sign. } else if (((low & 0x4000) > 0) && ((high & 0x4000) == 0)) { code ^= 0x4000; code &= 0xffff; low &= 0x3fff; low &= 0xffff; high |= 0x4000; high &= 0xffff; } else { // Nothing to shift out any more break; } low = (low << 1) & 0xffff; high = (high << 1) & 0xffff; high = (high | 1) & 0xffff; code = (code << 1) & 0xffff; if (bits == 0) { GetNextCodeText(bitStream, out bitBuffer, out bits); } code |= ((bitBuffer >> 31) & 0x00000001); bitBuffer <<= 1; bits--; } var symbol = int32ProbabilityContextTableEntry.Symbol; if (symbol != -2 || currentContext <= 0) { if (symbol == -2 && outOfBandDataCounter >= outOfBandValues.Length) { throw new Exception("'Out-Of-Band' data missing! Read values: " + i + " / " + symbolCount); } decodedSymbols.Add(symbol == -2 && outOfBandDataCounter < outOfBandValues.Length ? outOfBandValues[outOfBandDataCounter++] : int32ProbabilityContextTableEntry.AssociatedValue); } currentContext = int32ProbabilityContextTableEntry.NextContext; } } return(decodedSymbols.ToArray()); }
private static Int32ProbabilityContextTableEntry GetEntryAndSymbolRangeByRescaledCode(AccumulatedProbabilityCounts accumulatedProbabilityCounts, Int32ProbabilityContexts int32ProbabilityContexts, Int32 contextIndex, Int32 rescaledCode, ref Int32[] newSymbolRange) { var entryByAccumulatedCountPerContext = accumulatedProbabilityCounts.EntriesByAccumulatedCountPerContext[contextIndex]; var key = entryByAccumulatedCountPerContext.Keys.DefaultIfEmpty(-1).First(k => k > rescaledCode - 1); var value = entryByAccumulatedCountPerContext[key]; var int32ProbabilityContextTableEntry = int32ProbabilityContexts.ProbabilityContextTableEntries[contextIndex][value]; newSymbolRange[0] = key + 1 - int32ProbabilityContextTableEntry.OccurrenceCount; newSymbolRange[1] = key + 1; newSymbolRange[2] = accumulatedProbabilityCounts.SymbolCounts[contextIndex]; return(int32ProbabilityContextTableEntry); }