public HuffmanCodesBinaryTree() { valueToHuffmanCodeDictionary = new Dictionary <byte, Stack <bool> >(); binaryTree = new HackBinaryTree(); }
public static JpgHeaders readJpgFileHeader(ref byte[] fileBytes) { JpgHeaders jpgFileHeaders = new JpgHeaders(); jpgFileHeaders.fileOk = true; jpgFileHeaders.imageDataStartOffsetInBytes = 2; jpgFileHeaders.isLittleEndian = true; jpgFileHeaders.codeToSignedValueDictionary = new Dictionary <string, Int16>(); jpgFileHeaders.codeToSignedValueDictionary.Add("", 0); jpgFileHeaders.signedValueToCodeDictionary = new Dictionary <Int16, string>(); jpgFileHeaders.signedValueToCodeDictionary.Add(0, ""); jpgFileHeaders.huffmanCodesBinaryTrees = new Dictionary <byte, HuffmanCodesBinaryTree>(); Int16 rangeMin = -2047; Int16 rangeMax = 2047; Int16 currentStartingMinValue = -1; Int16 currentMinValue = 0; Int16 currentMaxValue = 0; byte codeLength = 1; while (currentMinValue > rangeMin && currentMaxValue < rangeMax) { Int16 numberOfValuesInCurrentHalfIteration = (Int16)(1 << (codeLength - 1)); Int16 currentValueIteration = 0; while (currentValueIteration < numberOfValuesInCurrentHalfIteration) { currentMinValue = (Int16)(currentStartingMinValue + currentValueIteration); jpgFileHeaders.codeToSignedValueDictionary.Add(binaryToString(currentValueIteration, codeLength), currentMinValue); jpgFileHeaders.signedValueToCodeDictionary.Add(currentMinValue, binaryToString(currentValueIteration, codeLength)); currentValueIteration++; } currentValueIteration = 0; while (currentValueIteration < numberOfValuesInCurrentHalfIteration) { currentMaxValue = (Int16)(numberOfValuesInCurrentHalfIteration + currentValueIteration); jpgFileHeaders.codeToSignedValueDictionary.Add(binaryToString((Int16)(numberOfValuesInCurrentHalfIteration + currentValueIteration), codeLength), currentMaxValue); jpgFileHeaders.signedValueToCodeDictionary.Add(currentMaxValue, binaryToString((Int16)(numberOfValuesInCurrentHalfIteration + currentValueIteration), codeLength)); currentValueIteration++; } currentStartingMinValue -= (Int16)(1 << (codeLength)); codeLength++; } MemoryStreamWithTypedReads binaryReader = new MemoryStreamWithTypedReads(fileBytes); UInt16 readMarker; bool firstPass = true; bool dataNotStarted = true; while (((readMarker = binaryReader.readUInt16()) != JpgMarkers.endOfImage) && jpgFileHeaders.fileOk && dataNotStarted) { dataNotStarted = readMarker != JpgMarkers.startOfScan; if (dataNotStarted) { switch (readMarker) { case (JpgMarkers.startOfHuffmanTables): { UInt16 expectedTablesLength = binaryReader.readUInt16(); jpgFileHeaders.imageDataStartOffsetInBytes += 2 + expectedTablesLength; for (UInt64 readBytes = 2; readBytes < expectedTablesLength; readBytes++) { UInt32 currentTableLength = 0; byte classAndIndetifierByte = binaryReader.readByte(); currentTableLength += 8; readBytes++; HuffmanCodesBinaryTree huffmanCodesBinaryTree = new HuffmanCodesBinaryTree(); ref HackBinaryTree currentBinaryTree = ref huffmanCodesBinaryTree.binaryTree; byte maxCodeLength = 0; byte[] extractedHuffmanCodeCounts = new byte[16]; for (int lengthOfCode = 1; lengthOfCode <= 16; lengthOfCode++) { extractedHuffmanCodeCounts[lengthOfCode - 1] = binaryReader.readByte(); currentTableLength += 8; readBytes++; } for (int lengthOfCode = 1; lengthOfCode <= 16; lengthOfCode++) { for (int codeIndex = 0; codeIndex < extractedHuffmanCodeCounts[lengthOfCode - 1]; codeIndex++) { maxCodeLength = (byte)lengthOfCode; HackBinaryTreeElement nextElement = currentBinaryTree.freeNodesAtCurrentDepth.Peek(); byte value = binaryReader.readByte(); huffmanCodesBinaryTree.valueToHuffmanCodeDictionary.Add(value, nextElement.unwind()); currentBinaryTree.addValue(value); currentTableLength += 8; readBytes++; } currentBinaryTree.addDepth(); } huffmanCodesBinaryTree.maxCodeLength = maxCodeLength; huffmanCodesBinaryTree.inFileLength = currentTableLength; jpgFileHeaders.huffmanCodesBinaryTrees.Add(classAndIndetifierByte, huffmanCodesBinaryTree); } } break;