/// <summary> /// Builds a new 8-bit huffmantree. The used algorithm is based on /// http://wiki.multimedia.cx/index.php?title=Smacker#Packed_Huffman_Trees /// </summary> /// <param name="m">The stream to build the tree from</param> public virtual void BuildTree(BitStream m) { //Read tag int tag = m.ReadBits(1); //If tag is zero, finish if (tag == 0) return; //Init tree rootNode = new Node(); BuildTree(m, rootNode); //For some reason we have to skip a bit m.ReadBits(1); }
public override void BuildTree(BitStream m) { //Read tag int tag = m.ReadBits(1); //If tag is zero, finish if (tag == 0) { return; } lowByteTree = new Huffmantree(); lowByteTree.BuildTree(m); highByteTree = new Huffmantree(); highByteTree.BuildTree(m); iMarker1 = m.ReadBits(16); //System.Console.WriteLine("M1:" + iMarker1); iMarker2 = m.ReadBits(16); //System.Console.WriteLine("M2:" + iMarker2); iMarker3 = m.ReadBits(16); //System.Console.WriteLine("M3:" + iMarker3); RootNode = new Node(); BuildTree(m, RootNode); //For some reason we have to skip a bit m.ReadBits(1); if (marker1 == null) { // System.Console.WriteLine("Not using marker 1"); marker1 = new Node(); } if (marker2 == null) { // System.Console.WriteLine("Not using marker 2"); marker2 = new Node(); } if (marker3 == null) { // System.Console.WriteLine("Not using marker 3"); marker3 = new Node(); } }
/// <summary> /// Builds a new 8-bit huffmantree. The used algorithm is based on /// http://wiki.multimedia.cx/index.php?title=Smacker#Packed_Huffman_Trees /// </summary> /// <param name="m">The stream to build the tree from</param> public virtual void BuildTree(BitStream m) { //Read tag int tag = m.ReadBits(1); //If tag is zero, finish if (tag == 0) { return; } //Init tree rootNode = new Node(); BuildTree(m, rootNode); //For some reason we have to skip a bit m.ReadBits(1); }
protected virtual void BuildTree(BitStream m, Node current) { //Read flag int flag = m.ReadBits(1); //If flag is nonzero if (flag != 0) { //Advance to "0"-branch Node left = new Node(); //Recursive call BuildTree(m, left); //The first left-node is actually the root if (current == null) { rootNode = left; return; } else { current.Left = left; } } else //If flag is zero { if (current == null) { current = new Node(); rootNode = current; } //Read 8 bit leaf int leaf = m.ReadBits(8); //Console.WriteLine("Decoded :" + leaf); current.IsLeaf = true; current.Value = leaf; return; } //Continue on the "1"-branch current.Right = new Node(); BuildTree(m, current.Right); }
/// <summary> /// Decodes a value using this tree based on the next bits in the specified stream /// </summary> /// <param name="m">The stream to read bits from</param> public virtual int Decode(BitStream m) { Node currentNode = RootNode; if (currentNode == null) { return(0); } while (!currentNode.isLeaf) { int bit = m.ReadBits(1); if (bit == 0) { currentNode = currentNode.Left; } else { currentNode = currentNode.Right; } } return(currentNode.Value); }
/// <summary> /// Decodes a value using this tree based on the next bits in the specified stream /// </summary> /// <param name="m">The stream to read bits from</param> public override int Decode(BitStream m) { //int v = base.Decode(m); Node currentNode = RootNode; if (currentNode == null) { return(0); } while (!currentNode.isLeaf) { int bit = m.ReadBits(1); if (bit == 0) { currentNode = currentNode.Left; } else { currentNode = currentNode.Right; } } int v = currentNode.Value; if (v != iMarker1) { iMarker3 = iMarker2; iMarker2 = iMarker1; iMarker1 = v; marker3.Value = marker2.Value; marker2.Value = marker1.Value; marker1.Value = v; } return(v); }
private void DecodeVideo() { uint x, y, mask, currentBlock = 0, runLength, colors, blockHeader, blockType = 0; uint posX, posY, index, pix, pix1, pix2, i, j; byte color, color1, color2; //Reset all huffman decoders File.MClr.ResetDecoder(); File.MMap.ResetDecoder(); File.Type.ResetDecoder(); File.Full.ResetDecoder(); //Allocate a new frame's data byte[] currentFrameData = new byte[File.Header.Width * File.Header.Height]; BitStream m = new BitStream(File.Stream); uint nbBlocksX = File.Header.Width / 4; uint nbBlocksY = File.Header.Height / 4; uint nbBlocks = nbBlocksX * nbBlocksY; long runLengthNotComplete = 0; while (currentBlock < nbBlocks) { blockHeader = (uint)File.Type.Decode(m); runLength = sizetable[(blockHeader >> 2) & 0x3F]; blockType = blockHeader & 3; // System.Console.Write("BLOCK " + currentBlock + " " + runLength + " "); switch (blockType) { case 2: //VOID BLOCK // System.Console.WriteLine("VOID - "); //Get block address for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { //Get current block coordinates posX = 4 * (currentBlock % nbBlocksX); posY = 4 * (currentBlock / nbBlocksX); index = 0; for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++) { index = GetIndex(posX + x, posY + y); currentFrameData[index] = lastFrameData[index]; } } currentBlock++; } runLengthNotComplete = runLength - i; break; case 3: //SOLID BLOCK // System.Console.WriteLine("SOLID - "); color = (byte)(blockHeader >> 8); //Get block address for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { //Get current block coordinates posX = 4 * (currentBlock % nbBlocksX); posY = 4 * (currentBlock / nbBlocksX); for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++) { currentFrameData[GetIndex(posX + x, posY + y)] = color; } } currentBlock++; } runLengthNotComplete = runLength - i; break; case 0: //MONO BLOCK // System.Console.WriteLine("MONO - "); for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { colors = (uint)File.MClr.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); mask = (uint)File.MMap.Decode(m); posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; for (y = 0; y < 4; y++) { if ((mask & 1) > 0) { currentFrameData[GetIndex(posX, posY + y)] = color1; } else { currentFrameData[GetIndex(posX, posY + y)] = color2; } if ((mask & 2) > 0) { currentFrameData[GetIndex(posX + 1, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 1, posY + y)] = color2; } if ((mask & 4) > 0) { currentFrameData[GetIndex(posX + 2, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 2, posY + y)] = color2; } if ((mask & 8) > 0) { currentFrameData[GetIndex(posX + 3, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 3, posY + y)] = color2; } mask >>= 4; } currentBlock++; } // runLengthNotComplete = runLength - i; break; case 1: // System.Console.WriteLine("FULL - "); int mode = 0; if (File.IsV4) { int type = m.ReadBits(1); if (type == 0) { int abit = m.ReadBits(1); if (abit == 1) mode = 2; } else mode = 1; } switch (mode) { case 0://v2 Full block for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; for (y = 0; y < 4; y++) { colors = (uint)File.Full.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); currentFrameData[GetIndex(posX + 3, posY + y)] = color1; currentFrameData[GetIndex(posX + 2, posY + y)] = color2; colors = (uint)File.Full.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); currentFrameData[GetIndex(posX + 1, posY + y)] = color1; currentFrameData[GetIndex(posX + 0, posY + y)] = color2; } currentBlock++; } break; case 1: for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; pix = (uint)File.Full.Decode(m); color1 = (byte)(pix >> 8); color2 = (byte)(pix & 0xFF); currentFrameData[GetIndex(posX + 0, posY + 0)] = color2; currentFrameData[GetIndex(posX + 1, posY + 0)] = color2; currentFrameData[GetIndex(posX + 2, posY + 0)] = color1; currentFrameData[GetIndex(posX + 3, posY + 0)] = color1; currentFrameData[GetIndex(posX + 0, posY + 1)] = color2; currentFrameData[GetIndex(posX + 1, posY + 1)] = color2; currentFrameData[GetIndex(posX + 2, posY + 1)] = color1; currentFrameData[GetIndex(posX + 3, posY + 1)] = color1; pix = (uint)File.Full.Decode(m); color1 = (byte)(pix >> 8); color2 = (byte)(pix & 0xFF); currentFrameData[GetIndex(posX + 0, posY + 2)] = color2; currentFrameData[GetIndex(posX + 1, posY + 2)] = color2; currentFrameData[GetIndex(posX + 2, posY + 2)] = color1; currentFrameData[GetIndex(posX + 3, posY + 2)] = color1; currentFrameData[GetIndex(posX + 0, posY + 3)] = color2; currentFrameData[GetIndex(posX + 1, posY + 3)] = color2; currentFrameData[GetIndex(posX + 2, posY + 3)] = color1; currentFrameData[GetIndex(posX + 3, posY + 3)] = color1; currentBlock++; } // runLengthNotComplete = runLength - i; break; case 2: for (j = 0; j < runLength && currentBlock < nbBlocks; j++) { posX = (currentBlock % nbBlocksX) << 2; posY = (currentBlock / nbBlocksX) << 2; for (i = 0; i < 2; i++) { pix1 = (uint)File.Full.Decode(m); pix2 = (uint)File.Full.Decode(m); color1 = (byte)(pix1 >> 8); color2 = (byte)(pix1 & 0xFF); currentFrameData[GetIndex(posX + 2, posY + (i << 1))] = color2; currentFrameData[GetIndex(posX + 3, posY + (i << 1))] = color1; currentFrameData[GetIndex(posX + 2, posY + (i << 1) + 1)] = color2; currentFrameData[GetIndex(posX + 3, posY + (i << 1) + 1)] = color1; color1 = (byte)(pix1 >> 8); color2 = (byte)(pix1 & 0xFF); currentFrameData[GetIndex(posX + 0, posY + (i << 1))] = color2; currentFrameData[GetIndex(posX + 1, posY + (i << 1))] = color1; currentFrameData[GetIndex(posX + 0, posY + (i << 1) + 1)] = color2; currentFrameData[GetIndex(posX + 1, posY + (i << 1) + 1)] = color1; } currentBlock++; } // runLengthNotComplete = runLength - j; break; default: break; } break; } } //if (runLengthNotComplete > 0) //{ // Console.WriteLine("Warning: frame ended before runlength has reached zero"); //} lastFrameData = currentFrameData; }
/// <summary> /// Reads the next frame. /// </summary> public void ReadNextFrame() { uint mask = 1; if (CurrentFrame >= File.Header.NbFrames) throw new EndOfStreamException("No more frames"); long currentPos = File.Stream.Position; //If this frame has a palette record if ((File.FrameTypes[CurrentFrame] & mask) > 0) { //Update the palette UpdatePalette(); } //Sound data mask <<= 1; for (int i = 0; i < 7; i++, mask <<= 1) { if ((file.FrameTypes[CurrentFrame] & mask) > 0) { long pos = File.Stream.Position; uint length = Util.ReadDWord(File.Stream); //We assume compression, if not, well too bad uint unpackedLength = Util.ReadDWord(File.Stream); BitStream m = new BitStream(File.Stream); if (m.ReadBits(1) != 0) //Audio present { bool stereo = m.ReadBits(1) > 0; bool is16Bit = m.ReadBits(1) > 0; //Next are some trees uint nbTrees = 1; if (stereo) nbTrees <<= 1; if (is16Bit) nbTrees <<= 1; Huffmantree[] tree = new Huffmantree[nbTrees]; byte[] audioData = new byte[unpackedLength + 4]; uint audioDataIndex = 0; for (int k = 0; k < nbTrees; k++) { tree[k] = new Huffmantree(); tree[k].BuildTree(m); } int res; if (is16Bit) { Int16 rightBaseMSB = 0, rightBaseLSB = 0, leftBaseMSB = 0, leftBaseLSB = 0; rightBaseMSB = (Int16)(m.ReadBits(8)); rightBaseLSB = (Int16)(m.ReadBits(8)); //Add sample (little endian) audioData[audioDataIndex++] = (byte)rightBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)rightBaseMSB; //Higher byte if (stereo) { leftBaseMSB = (Int16)(m.ReadBits(8)); leftBaseLSB = (Int16)(m.ReadBits(8)); //Add sample (little endian) audioData[audioDataIndex++] = (byte)leftBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)leftBaseMSB; //Higher byte } for (int l = 0; l < unpackedLength / 2; l++) { if ((l & ((stereo) ? 1 : 0)) > 0) { res = tree[2].Decode(m); leftBaseLSB += (Int16)res; res = tree[3].Decode(m); leftBaseMSB += (Int16)res; leftBaseMSB += (Int16)(leftBaseLSB >> 8); leftBaseLSB &= 0xFF; //Add sample (little endian) audioData[audioDataIndex++] = (byte)leftBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)leftBaseMSB; //Higher byte } else { res = tree[0].Decode(m); rightBaseLSB += (Int16)res; res = tree[1].Decode(m); rightBaseMSB += (Int16)res; rightBaseMSB += (Int16)(rightBaseLSB >> 8); rightBaseLSB &= 0xFF; //Add sample (little endian) audioData[audioDataIndex++] = (byte)rightBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)rightBaseMSB; //Higher byte } } } else { byte rightBase = (byte)m.ReadBits(8), leftBase = 0; //Add sample audioData[audioDataIndex++] = rightBase; if (stereo) { leftBase = (byte)m.ReadBits(8); //Add sample audioData[audioDataIndex++] = leftBase; } for (int l = 0; l < unpackedLength; l++) { if ((l & ((stereo) ? 1 : 0)) > 0) { leftBase += (byte)tree[1].Decode(m); //Add sample audioData[audioDataIndex++] = leftBase; } else { rightBase += (byte)tree[0].Decode(m); //Add sample audioData[audioDataIndex++] = rightBase; } } } lastAudioData[i] = audioData; } File.Stream.Seek(pos + (long)length, SeekOrigin.Begin); } } //Video data try { DecodeVideo(); } catch (IOException exc) { Console.WriteLine("Exception caught while decoding frame:" + exc.ToString()); } //Seek to the next frame File.Stream.Seek(currentPos + File.FrameSizes[CurrentFrame], SeekOrigin.Begin); CurrentFrame++; }
/// <summary> /// Decodes a value using this tree based on the next bits in the specified stream /// </summary> /// <param name="m">The stream to read bits from</param> public virtual int Decode(BitStream m) { Node currentNode = RootNode; if (currentNode == null) return 0; while (!currentNode.isLeaf) { int bit = m.ReadBits(1); if (bit == 0) { currentNode = currentNode.Left; } else { currentNode = currentNode.Right; } } return currentNode.Value; }
protected override void BuildTree(BitStream m, Node current) { //Read flag int flag = m.ReadBits(1); //If flag is nonzero if (flag != 0) { //Advance to "0"-branch Node left = new Node(); //Recursive call BuildTree(m, left); //The first left-node is actually the root if (current == null) { RootNode = left; return; } else current.Left = left; } else //If flag is zero { if (current == null) { current = new Node(); RootNode = current; } //Read 16 bit leaf by decoding the low byte, then the high byte int lower = lowByteTree.Decode(m); int higher = highByteTree.Decode(m); int leaf = lower | (higher << 8); //System.Console.WriteLine("Decoded: " + leaf); //If we found one of the markers, store pointers to those nodes. if (leaf == iMarker1) { leaf = 0; marker1 = current; } if (leaf == iMarker2) { leaf = 0; marker2 = current; } if (leaf == iMarker3) { leaf = 0; marker3 = current; } current.IsLeaf = true; current.Value = leaf; return; } //Continue on the "1"-branch current.Right = new Node(); BuildTree(m, current.Right); }
public override void BuildTree(BitStream m) { //Read tag int tag = m.ReadBits(1); //If tag is zero, finish if (tag == 0) return; lowByteTree = new Huffmantree(); lowByteTree.BuildTree(m); highByteTree = new Huffmantree(); highByteTree.BuildTree(m); iMarker1 = m.ReadBits(16); //System.Console.WriteLine("M1:" + iMarker1); iMarker2 = m.ReadBits(16); //System.Console.WriteLine("M2:" + iMarker2); iMarker3 = m.ReadBits(16); //System.Console.WriteLine("M3:" + iMarker3); RootNode = new Node(); BuildTree(m, RootNode); //For some reason we have to skip a bit m.ReadBits(1); if (marker1 == null) { // System.Console.WriteLine("Not using marker 1"); marker1 = new Node(); } if (marker2 == null) { // System.Console.WriteLine("Not using marker 2"); marker2 = new Node(); } if (marker3 == null) { // System.Console.WriteLine("Not using marker 3"); marker3 = new Node(); } }
/// <summary> /// Decodes a value using this tree based on the next bits in the specified stream /// </summary> /// <param name="m">The stream to read bits from</param> public override int Decode(BitStream m) { //int v = base.Decode(m); Node currentNode = RootNode; if (currentNode == null) return 0; while (!currentNode.isLeaf) { int bit = m.ReadBits(1); if (bit == 0) { currentNode = currentNode.Left; } else { currentNode = currentNode.Right; } } int v = currentNode.Value; if (v != iMarker1) { iMarker3 = iMarker2; iMarker2 = iMarker1; iMarker1 = v; marker3.Value = marker2.Value; marker2.Value = marker1.Value; marker1.Value = v; } return v; }
protected virtual void BuildTree(BitStream m, Node current) { //Read flag int flag = m.ReadBits(1); //If flag is nonzero if (flag != 0) { //Advance to "0"-branch Node left = new Node(); //Recursive call BuildTree(m, left); //The first left-node is actually the root if (current == null) { rootNode = left; return; } else current.Left = left; } else //If flag is zero { if (current == null) { current = new Node(); rootNode = current; } //Read 8 bit leaf int leaf = m.ReadBits(8); //Console.WriteLine("Decoded :" + leaf); current.IsLeaf = true; current.Value = leaf; return; } //Continue on the "1"-branch current.Right = new Node(); BuildTree(m, current.Right); }
protected override void BuildTree(BitStream m, Node current) { //Read flag int flag = m.ReadBits(1); //If flag is nonzero if (flag != 0) { //Advance to "0"-branch Node left = new Node(); //Recursive call BuildTree(m, left); //The first left-node is actually the root if (current == null) { RootNode = left; return; } else { current.Left = left; } } else //If flag is zero { if (current == null) { current = new Node(); RootNode = current; } //Read 16 bit leaf by decoding the low byte, then the high byte int lower = lowByteTree.Decode(m); int higher = highByteTree.Decode(m); int leaf = lower | (higher << 8); //System.Console.WriteLine("Decoded: " + leaf); //If we found one of the markers, store pointers to those nodes. if (leaf == iMarker1) { leaf = 0; marker1 = current; } if (leaf == iMarker2) { leaf = 0; marker2 = current; } if (leaf == iMarker3) { leaf = 0; marker3 = current; } current.IsLeaf = true; current.Value = leaf; return; } //Continue on the "1"-branch current.Right = new Node(); BuildTree(m, current.Right); }
private void DecodeVideo() { uint x, y, mask, currentBlock = 0, runLength, colors, blockHeader, blockType = 0; uint posX, posY, index, pix, pix1, pix2, i, j; byte color, color1, color2; //Reset all huffman decoders File.MClr.ResetDecoder(); File.MMap.ResetDecoder(); File.Type.ResetDecoder(); File.Full.ResetDecoder(); //Allocate a new frame's data byte[] currentFrameData = new byte[File.Header.Width * File.Header.Height]; BitStream m = new BitStream(File.Stream); uint nbBlocksX = File.Header.Width / 4; uint nbBlocksY = File.Header.Height / 4; uint nbBlocks = nbBlocksX * nbBlocksY; long runLengthNotComplete = 0; while (currentBlock < nbBlocks) { blockHeader = (uint)File.Type.Decode(m); runLength = sizetable[(blockHeader >> 2) & 0x3F]; blockType = blockHeader & 3; // System.Console.Write("BLOCK " + currentBlock + " " + runLength + " "); switch (blockType) { case 2: //VOID BLOCK // System.Console.WriteLine("VOID - "); //Get block address for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { //Get current block coordinates posX = 4 * (currentBlock % nbBlocksX); posY = 4 * (currentBlock / nbBlocksX); index = 0; for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++) { index = GetIndex(posX + x, posY + y); currentFrameData[index] = lastFrameData[index]; } } currentBlock++; } runLengthNotComplete = runLength - i; break; case 3: //SOLID BLOCK // System.Console.WriteLine("SOLID - "); color = (byte)(blockHeader >> 8); //Get block address for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { //Get current block coordinates posX = 4 * (currentBlock % nbBlocksX); posY = 4 * (currentBlock / nbBlocksX); for (x = 0; x < 4; x++) { for (y = 0; y < 4; y++) { currentFrameData[GetIndex(posX + x, posY + y)] = color; } } currentBlock++; } runLengthNotComplete = runLength - i; break; case 0: //MONO BLOCK // System.Console.WriteLine("MONO - "); for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { colors = (uint)File.MClr.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); mask = (uint)File.MMap.Decode(m); posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; for (y = 0; y < 4; y++) { if ((mask & 1) > 0) { currentFrameData[GetIndex(posX, posY + y)] = color1; } else { currentFrameData[GetIndex(posX, posY + y)] = color2; } if ((mask & 2) > 0) { currentFrameData[GetIndex(posX + 1, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 1, posY + y)] = color2; } if ((mask & 4) > 0) { currentFrameData[GetIndex(posX + 2, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 2, posY + y)] = color2; } if ((mask & 8) > 0) { currentFrameData[GetIndex(posX + 3, posY + y)] = color1; } else { currentFrameData[GetIndex(posX + 3, posY + y)] = color2; } mask >>= 4; } currentBlock++; } // runLengthNotComplete = runLength - i; break; case 1: // System.Console.WriteLine("FULL - "); int mode = 0; if (File.IsV4) { int type = m.ReadBits(1); if (type == 0) { int abit = m.ReadBits(1); if (abit == 1) { mode = 2; } } else { mode = 1; } } switch (mode) { case 0: //v2 Full block for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; for (y = 0; y < 4; y++) { colors = (uint)File.Full.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); currentFrameData[GetIndex(posX + 3, posY + y)] = color1; currentFrameData[GetIndex(posX + 2, posY + y)] = color2; colors = (uint)File.Full.Decode(m); color1 = (byte)(colors >> 8); color2 = (byte)(colors & 0xFF); currentFrameData[GetIndex(posX + 1, posY + y)] = color1; currentFrameData[GetIndex(posX + 0, posY + y)] = color2; } currentBlock++; } break; case 1: for (i = 0; i < runLength && currentBlock < nbBlocks; i++) { posX = (currentBlock % nbBlocksX) * 4; posY = (currentBlock / nbBlocksX) * 4; pix = (uint)File.Full.Decode(m); color1 = (byte)(pix >> 8); color2 = (byte)(pix & 0xFF); currentFrameData[GetIndex(posX + 0, posY + 0)] = color2; currentFrameData[GetIndex(posX + 1, posY + 0)] = color2; currentFrameData[GetIndex(posX + 2, posY + 0)] = color1; currentFrameData[GetIndex(posX + 3, posY + 0)] = color1; currentFrameData[GetIndex(posX + 0, posY + 1)] = color2; currentFrameData[GetIndex(posX + 1, posY + 1)] = color2; currentFrameData[GetIndex(posX + 2, posY + 1)] = color1; currentFrameData[GetIndex(posX + 3, posY + 1)] = color1; pix = (uint)File.Full.Decode(m); color1 = (byte)(pix >> 8); color2 = (byte)(pix & 0xFF); currentFrameData[GetIndex(posX + 0, posY + 2)] = color2; currentFrameData[GetIndex(posX + 1, posY + 2)] = color2; currentFrameData[GetIndex(posX + 2, posY + 2)] = color1; currentFrameData[GetIndex(posX + 3, posY + 2)] = color1; currentFrameData[GetIndex(posX + 0, posY + 3)] = color2; currentFrameData[GetIndex(posX + 1, posY + 3)] = color2; currentFrameData[GetIndex(posX + 2, posY + 3)] = color1; currentFrameData[GetIndex(posX + 3, posY + 3)] = color1; currentBlock++; } // runLengthNotComplete = runLength - i; break; case 2: for (j = 0; j < runLength && currentBlock < nbBlocks; j++) { posX = (currentBlock % nbBlocksX) << 2; posY = (currentBlock / nbBlocksX) << 2; for (i = 0; i < 2; i++) { pix1 = (uint)File.Full.Decode(m); pix2 = (uint)File.Full.Decode(m); color1 = (byte)(pix1 >> 8); color2 = (byte)(pix1 & 0xFF); currentFrameData[GetIndex(posX + 2, posY + (i << 1))] = color2; currentFrameData[GetIndex(posX + 3, posY + (i << 1))] = color1; currentFrameData[GetIndex(posX + 2, posY + (i << 1) + 1)] = color2; currentFrameData[GetIndex(posX + 3, posY + (i << 1) + 1)] = color1; color1 = (byte)(pix1 >> 8); color2 = (byte)(pix1 & 0xFF); currentFrameData[GetIndex(posX + 0, posY + (i << 1))] = color2; currentFrameData[GetIndex(posX + 1, posY + (i << 1))] = color1; currentFrameData[GetIndex(posX + 0, posY + (i << 1) + 1)] = color2; currentFrameData[GetIndex(posX + 1, posY + (i << 1) + 1)] = color1; } currentBlock++; } // runLengthNotComplete = runLength - j; break; default: break; } break; } } //if (runLengthNotComplete > 0) //{ // Console.WriteLine("Warning: frame ended before runlength has reached zero"); //} lastFrameData = currentFrameData; }
/// <summary> /// Reads the next frame. /// </summary> public void ReadNextFrame() { uint mask = 1; if (CurrentFrame >= File.Header.NbFrames) { throw new EndOfStreamException("No more frames"); } long currentPos = File.Stream.Position; //If this frame has a palette record if ((File.FrameTypes[CurrentFrame] & mask) > 0) { //Update the palette UpdatePalette(); } //Sound data mask <<= 1; for (int i = 0; i < 7; i++, mask <<= 1) { if ((file.FrameTypes[CurrentFrame] & mask) > 0) { long pos = File.Stream.Position; uint length = Util.ReadDWord(File.Stream); //We assume compression, if not, well too bad uint unpackedLength = Util.ReadDWord(File.Stream); BitStream m = new BitStream(File.Stream); if (m.ReadBits(1) != 0) //Audio present { bool stereo = m.ReadBits(1) > 0; bool is16Bit = m.ReadBits(1) > 0; //Next are some trees uint nbTrees = 1; if (stereo) { nbTrees <<= 1; } if (is16Bit) { nbTrees <<= 1; } Huffmantree[] tree = new Huffmantree[nbTrees]; byte[] audioData = new byte[unpackedLength + 4]; uint audioDataIndex = 0; for (int k = 0; k < nbTrees; k++) { tree[k] = new Huffmantree(); tree[k].BuildTree(m); } int res; if (is16Bit) { Int16 rightBaseMSB = 0, rightBaseLSB = 0, leftBaseMSB = 0, leftBaseLSB = 0; rightBaseMSB = (Int16)(m.ReadBits(8)); rightBaseLSB = (Int16)(m.ReadBits(8)); //Add sample (little endian) audioData[audioDataIndex++] = (byte)rightBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)rightBaseMSB; //Higher byte if (stereo) { leftBaseMSB = (Int16)(m.ReadBits(8)); leftBaseLSB = (Int16)(m.ReadBits(8)); //Add sample (little endian) audioData[audioDataIndex++] = (byte)leftBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)leftBaseMSB; //Higher byte } for (int l = 0; l < unpackedLength / 2; l++) { if ((l & ((stereo) ? 1 : 0)) > 0) { res = tree[2].Decode(m); leftBaseLSB += (Int16)res; res = tree[3].Decode(m); leftBaseMSB += (Int16)res; leftBaseMSB += (Int16)(leftBaseLSB >> 8); leftBaseLSB &= 0xFF; //Add sample (little endian) audioData[audioDataIndex++] = (byte)leftBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)leftBaseMSB; //Higher byte } else { res = tree[0].Decode(m); rightBaseLSB += (Int16)res; res = tree[1].Decode(m); rightBaseMSB += (Int16)res; rightBaseMSB += (Int16)(rightBaseLSB >> 8); rightBaseLSB &= 0xFF; //Add sample (little endian) audioData[audioDataIndex++] = (byte)rightBaseLSB; //Lower byte audioData[audioDataIndex++] = (byte)rightBaseMSB; //Higher byte } } } else { byte rightBase = (byte)m.ReadBits(8), leftBase = 0; //Add sample audioData[audioDataIndex++] = rightBase; if (stereo) { leftBase = (byte)m.ReadBits(8); //Add sample audioData[audioDataIndex++] = leftBase; } for (int l = 0; l < unpackedLength; l++) { if ((l & ((stereo) ? 1 : 0)) > 0) { leftBase += (byte)tree[1].Decode(m); //Add sample audioData[audioDataIndex++] = leftBase; } else { rightBase += (byte)tree[0].Decode(m); //Add sample audioData[audioDataIndex++] = rightBase; } } } lastAudioData[i] = audioData; } File.Stream.Seek(pos + (long)length, SeekOrigin.Begin); } } //Video data try { DecodeVideo(); } catch (IOException exc) { Console.WriteLine("Exception caught while decoding frame:" + exc.ToString()); } //Seek to the next frame File.Stream.Seek(currentPos + File.FrameSizes[CurrentFrame], SeekOrigin.Begin); CurrentFrame++; }