Example #1
0
        /// <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);

        }
Example #2
0
        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();
            }
        }
Example #3
0
        /// <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);
        }
Example #4
0
        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);
        }
Example #5
0
        /// <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);
        }
Example #6
0
        /// <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);
        }
Example #7
0
        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;
        }
Example #8
0
        /// <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++;
        }
Example #9
0
 /// <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;
 }
Example #10
0
        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);
        }
Example #11
0
        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();
	    }

        }
Example #12
0
        /// <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;
        }
Example #13
0
        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);
        }
Example #14
0
        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);
        }
Example #15
0
        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;
        }
Example #16
0
        /// <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++;
        }