Exemple #1
0
        public void TestReadBitAndAdvanceStream()
        {
            var sourceBytes = new byte[1];

            sourceBytes[0] = 130; //1000 0010

            var bitStreamManager = new BitStreamManager(sourceBytes);

            Assert.AreEqual(0, bitStreamManager.Position);

            //Le um bit e verifica se ele é off;
            //o Stream resultante ficou assim: 1000 001
            Assert.IsFalse(bitStreamManager.ReadBit());


            Assert.AreEqual(1, bitStreamManager.Position);

            //Verifica que o stream não terminou
            Assert.IsFalse(bitStreamManager.EndOfStream);

            //Le mais 7 bits
            byte result = bitStreamManager.ReadValue(7);

            //65 = 0100 0001 porque o bit mais significante foi completado em branco.
            Assert.AreEqual(65, result);
        }
Exemple #2
0
        private void DecodeCompressed(StripData strip)
        {
            _numBitPerPaletteEntry = strip.CodecId - strip.ParamSubtraction;
            _substrationVariable   = 1;
            _bitStreamManager      = new BitStreamManager(strip.ImageData);

            _currentLine   = 0;
            _currentColumn = 0;
            bool finishDecode = false;

            //if (strip.CodecId >= 0x54 && strip.CodecId <= 0x58) Debugger.Break();
            //if (strip.CodecId >= 0x40 && strip.CodecId <= 0x44) Debugger.Break();

            //Read palette and Draw the first pixel.
            _paletteIndex = _bitStreamManager.ReadByte();

            SetCurrentColor();

            _resultBitmap.SetPixel(_currentOffset + _currentColumn, _currentLine, _currentColor);

            while (!finishDecode)
            {
                var changeAction = _bitStreamManager.ReadBit();
                //changeAction = false (0): Draw next pixel with current palette index.
                //                          Otherwise changeAction is true and we need the next bit to decide what to do.

                //changeAction = true (1): We need the next bit to discover what to do.
                if (changeAction)
                {
                    if (strip.CompressionType == CompressionTypes.Method1)
                    {
                        DecodeCode1Specifics();
                    }
                    else if (strip.CompressionType == CompressionTypes.Method2)
                    {
                        DecodeCode2Specifics();
                    }
                }
                else
                {
                    DrawNextPixel();
                }


                if ((_currentColumn == 7 && _currentLine == (_height - 1)) || _bitStreamManager.EndOfStream)
                {
                    finishDecode = true;
                }
            }

            UsedIndexes.Sort();
        }
Exemple #3
0
        public void TestArrayRebuild()
        {
            var sourceBytes = new byte[2];

            sourceBytes[0] = 100; //0110 0100
            sourceBytes[1] = 54;  //0011 0110

            var bitStreamManager = new BitStreamManager(sourceBytes);

            Assert.AreEqual(16, bitStreamManager.Lenght);

            byte[] rebuildBytes = bitStreamManager.ToByteArray();

            Assert.AreEqual(sourceBytes[0], rebuildBytes[0]);
            Assert.AreEqual(sourceBytes[1], rebuildBytes[1]);
        }
Exemple #4
0
        public void TestB()
        {
            //0x11 (17)  - 0000 1011
            //0x05 (5)   - 0000 0101
            //0x80 (128) - 1000 0000
            //0xFC (252) - 1111 1100

            var bs = new BitStreamManager(new byte[] { 0x11, 0x05, 0x80, 0xFC });
            //int pSize = 7;

            var compression = bs.ReadByte();

            Assert.AreEqual(0x11, compression);

            Assert.AreEqual(0x05, bs.ReadByte()); //le o numero da palheta;

            //0x80

            //Desenha tudo na mesma paletta.
            Assert.AreEqual(false, bs.ReadBit()); //0
            Assert.AreEqual(false, bs.ReadBit()); //0
            Assert.AreEqual(false, bs.ReadBit()); //0
            Assert.AreEqual(false, bs.ReadBit()); //0

            Assert.AreEqual(false, bs.ReadBit()); //0
            Assert.AreEqual(false, bs.ReadBit()); //0
            Assert.AreEqual(false, bs.ReadBit()); //0

            //Encontrou bit de controle.
            Assert.AreEqual(true, bs.ReadBit());  //1

            //0xFC

            //Bit 0 - le o próximo indice da palheta (7 bits)
            Assert.AreEqual(false, bs.ReadBit()); //0

            Assert.AreEqual(0x7E, bs.ReadValue(7));
            //Assert.AreEqual(false, bs.ReadBit()); //0
            //Assert.AreEqual(true, bs.ReadBit());  //1
            //Assert.AreEqual(true, bs.ReadBit());  //1

            //Assert.AreEqual(true, bs.ReadBit());  //1
            //Assert.AreEqual(true, bs.ReadBit());  //1
            //Assert.AreEqual(true, bs.ReadBit());  //1
            //Assert.AreEqual(true, bs.ReadBit());  //1
        }
Exemple #5
0
        private void DecodeZPlaneStrip(ZPlaneStripData strip)
        {
            _bitStreamManager = new BitStreamManager(strip.ImageData);
            bool finishDecode = false;

            while (!finishDecode)
            {
                byte count = _bitStreamManager.ReadByte();
                if (count > 0)
                {
                    if (BinaryHelper.CheckBitState(count, 7))
                    {                                                   // write the same byte count times
                        count = BinaryHelper.GetBitsFromByte(count, 7); // &= 0x7F;
                        byte b = _bitStreamManager.ReadByte();

                        for (int i = 0; i < count; i++)
                        {
                            if (!CheckEndOfGraphics())
                            {
                                DrawLine(b);
                            }
                        }
                    }
                    else
                    {  // write count bytes as is from the input
                        for (int i = 0; i < count; i++)
                        {
                            if (!CheckEndOfGraphics())
                            {
                                DrawLine(_bitStreamManager.ReadByte());
                            }
                        }
                    }
                }
                //else
                //{
                //    Debugger.Break();
                //}

                if (CheckEndOfGraphics() || _bitStreamManager.EndOfStream)
                {
                    finishDecode = true;
                }
            }
        }
Exemple #6
0
        public void TestC()
        {
            //            else if (highestPaletteIndex >= 16 && highestPaletteIndex <= 31)
            //{
            //     paletteBitSize = 5;//max 31 values;

            BitStreamManager bs = new BitStreamManager();

            bs.AddBit(true);
            bs.AddBit(false);
            bs.AddByte(28, 5);

            byte[] values = bs.ToByteArray();
            bs = new BitStreamManager(values);

            Assert.IsTrue(bs.ReadBit());
            Assert.IsFalse(bs.ReadBit());
            Assert.AreEqual(28, bs.ReadValue(6));
            //Assert.IsFalse(bs.ReadBit());
        }
Exemple #7
0
        private void DecodeUncompressed(StripData strip)
        {
            _bitStreamManager = new BitStreamManager(strip.ImageData);

            bool finishDecode = false;

            _paletteIndex = _bitStreamManager.ReadByte();
            SetCurrentColor();
            _resultBitmap.SetPixel(_currentOffset, 0, _currentColor);

            while (!finishDecode)
            {
                _paletteIndex = _bitStreamManager.ReadByte();
                SetCurrentColor();
                DrawNextPixel();
                if ((_currentColumn == 7 && _currentLine == (_height - 1)) || _bitStreamManager.EndOfStream)
                {
                    finishDecode = true;
                }
            }
        }
Exemple #8
0
        public void TestArrayBuildFromBitPopulated()
        {
            var bitStreamManager = new BitStreamManager();

            //100 = 0110 0100
            bitStreamManager.AddBit(false);
            bitStreamManager.AddBit(false);
            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(false);

            bitStreamManager.AddBit(false);
            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(false);

            //54 = 0011 0110
            bitStreamManager.AddBit(false);
            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(false);

            bitStreamManager.AddBit(true);
            bitStreamManager.AddBit(true);
            //Deixa esses dois em branco, e o bitStream tem que preencher com 0s...
            //bitStreamManager.AddBit(false);
            //bitStreamManager.AddBit(false);

            var sourceBytes = new byte[2];

            sourceBytes[0] = 100; //0110 0100
            sourceBytes[1] = 54;  //


            Assert.AreEqual(14, bitStreamManager.Lenght);

            byte[] rebuildBytes = bitStreamManager.ToByteArray();

            Assert.AreEqual(sourceBytes[0], rebuildBytes[0]);
            Assert.AreEqual(sourceBytes[1], rebuildBytes[1]);
        }
Exemple #9
0
        private void WriteAccumulatedColor(BitStreamManager bitStream, byte accumulatedSameColor)
        {
            if (accumulatedSameColor > 12)
            {
                //Add the change action bits:
                //   11: Read the next 3 bit value, and perform an action, depending on the value:
                bitStream.AddBit(true);
                bitStream.AddBit(true);
                //Add the count bit action code: 100 (4): Read next 8 bits. Draw the number of pixels specified by these 8 bits with the current palette index (somewhat similar to RLE).
                bitStream.AddByte(4, 3);

                //Add the number of pixels that will be draw with this color.
                bitStream.AddByte(accumulatedSameColor);
            }
            else
            {
                for (int i = 0; i < accumulatedSameColor; i++)
                {
                    bitStream.AddBit(false);
                }
            }
        }
Exemple #10
0
        private StripData EncodeUncompressed()
        {
            var strip     = new StripData();
            var bitStream = new BitStreamManager();

            strip.CodecId = 0x01;

            _renderdingDirection = strip.RenderdingDirection;
            _currentLocation.X   = 0;
            _currentLocation.Y   = 0;

            int firstPaletteIndex = FindTableIndex(_imageToEncode.GetPixel(_currentOffset + 0, 0));

            bitStream.AddByte((byte)firstPaletteIndex);

            while (!(_currentLocation.X == 7 && _currentLocation.Y == (_height - 1)))
            {
                var paletteIndex = FindTableIndex(GetNextPixel());
                bitStream.AddByte((byte)paletteIndex);
            }

            strip.ImageData = bitStream.ToByteArray();
            return(strip);
        }
        //  lines
        //    encoded size : 16le
        //    line data    : size bytes
        private void Encode()
        {
            var result = new List <byte>();

            _currentLine = 0;

            //Primeira passagem - Cadastra tudo alternado
            while (_currentLine < (_height))
            {
                var bitStream       = new BitStreamManager();
                var lineInformation = new List <SegmentInformation>();

                var  currentSegmentInformation = new SegmentInformation();
                byte lastColorIndex            = (byte)FindTableIndex(_imageToEncode.GetPixel(0, _currentLine));
                if (lastColorIndex == (byte)FindTableIndex(_imageToEncode.GetPixel(1, _currentLine)))
                {
                    currentSegmentInformation.RepeatSameColor = true;
                }
                currentSegmentInformation.Colors.Add(lastColorIndex);

                for (int x = 1; x < _width; x++)
                {
                    byte currentColorIndex = (byte)FindTableIndex(_imageToEncode.GetPixel(x, _currentLine));

                    if (currentColorIndex != lastColorIndex)
                    {
                        if (currentSegmentInformation.RepeatSameColor)
                        {
                            //Mudou de REPETIR para NÃO REPETIR
                            lineInformation.Add(currentSegmentInformation);

                            currentSegmentInformation = new SegmentInformation();
                            currentSegmentInformation.RepeatSameColor = false;
                        }
                    }
                    else
                    {
                        if (!currentSegmentInformation.RepeatSameColor)
                        {
                            //Mudou de NÃO REPETIR para REPETIR
                            lineInformation.Add(currentSegmentInformation);

                            currentSegmentInformation = new SegmentInformation();
                            currentSegmentInformation.RepeatSameColor = true;
                        }
                    }

                    currentSegmentInformation.Colors.Add(currentColorIndex);

                    lastColorIndex = currentColorIndex;
                }

                lineInformation.Add(currentSegmentInformation);

                //Segunda passagem - verifica a lista de itens não repetidos para ver se o ultimo elemento é um elemento da lista repetida seguinte.
                for (int i = 1; i < lineInformation.Count; i++)
                {
                    var previous          = lineInformation[i - 1];
                    var previousLastIndex = previous.Colors.Count - 1;
                    var current           = lineInformation[i - 1];

                    if (!previous.RepeatSameColor && current.RepeatSameColor && previous.Colors[previousLastIndex] == current.Colors[0])
                    {
                        //move o item da lista anterior para a lista atual
                        current.Colors.Insert(0, previous.Colors[previousLastIndex]);

                        previous.Colors.RemoveAt(previousLastIndex);
                    }
                }

                //Terceira passagem - procura por listas que eventualmente ficaram vazias, e as remove.
                //É importante percorrer a lista ao contrários, caso contrário a lista sera lida errada, além de dar IndexOutOfBounds no final.
                for (int i = lineInformation.Count - 1; i >= 0; i--)
                {
                    if (lineInformation[i].Colors.Count == 0)
                    {
                        lineInformation.RemoveAt(i);
                    }
                }

                //Quarta passagem, divide as listas com mais de 128 itens em varias listas, pois 128 é o limite máximo de 7 bits + 1.
                var finalLineInformation = new List <SegmentInformation>();
                foreach (SegmentInformation segmentInformation in lineInformation)
                {
                    if (segmentInformation.Colors.Count > 128)
                    {
                        while (segmentInformation.Colors.Count > 128)
                        {
                            var dividedLineInformation = new SegmentInformation();
                            dividedLineInformation.RepeatSameColor = segmentInformation.RepeatSameColor;
                            dividedLineInformation.Colors.AddRange(segmentInformation.Colors.Take(128).ToArray());

                            finalLineInformation.Add(dividedLineInformation);

                            segmentInformation.Colors = segmentInformation.Colors.Skip(128).ToList();
                        }
                    }
                    finalLineInformation.Add(segmentInformation);
                }

                //Quinta passagem, grava o BitStream.
                foreach (SegmentInformation segmentInformation in finalLineInformation)
                {
                    bitStream.AddBit(segmentInformation.RepeatSameColor);
                    if (segmentInformation.RepeatSameColor)
                    {
                        bitStream.AddByte((byte)(segmentInformation.Colors.Count - 1), 7);
                        bitStream.AddByte(segmentInformation.Colors[0]);
                    }
                    else
                    {
                        bitStream.AddByte((byte)(segmentInformation.Colors.Count - 1), 7);
                        foreach (byte differentLine in segmentInformation.Colors)
                        {
                            bitStream.AddByte(differentLine);
                        }
                    }
                }

                _currentLine++;

                byte[] encodedLine = bitStream.ToByteArray();
                result.AddRange(BinaryHelper.UInt16ToBytes((ushort)encodedLine.Length));
                result.AddRange(encodedLine);
            }

            _imageBomp.Data = result.ToArray();
        }
        public void Decode()
        {
            UsedIndexes = new List <int>();

            _currentLine   = 0;
            _currentColumn = 0;

            var bitStreamManager = new BitStreamManager(_imageData.Data);

            _resultBitmap = new Bitmap(_width, _height);

            //if (_pictureData.ImageData.Length == 0
            //    || (_pictureData.ImageData.Length == 1 && _pictureData.ImageData[0] == 0)) return; //Algumas imagens são vazias!!

            /*
             * Each line start with a 16le storing the size of the encoded line (without the size header itself) followed by the RLE data.
             * lines
             *  encoded size : 16le
             *  line data    : size bytes
             */
            bool finishDecode = false;

            while (!finishDecode)
            {
                uint lineSize       = bitStreamManager.ReadUInt16();
                int  streamPosition = bitStreamManager.Position;

                while ((bitStreamManager.Position - streamPosition) < (lineSize * 8))
                {
                    bool repeatSameColor = bitStreamManager.ReadBit();
                    int  count           = bitStreamManager.ReadValue(7) + 1;

                    if (count > _width)
                    {
                        count = _width;
                    }

                    if (repeatSameColor)
                    {
                        byte colorIndex = bitStreamManager.ReadByte();
                        var  color      = GetColor(colorIndex);
                        for (int j = 0; j < count; j++)
                        {
                            DrawNextPixel(color);
                        }
                    }
                    else
                    {
                        for (int j = 0; j < count; j++)
                        {
                            byte colorIndex = bitStreamManager.ReadByte();
                            var  color      = GetColor(colorIndex);
                            DrawNextPixel(color);
                        }
                    }

                    if ((_currentColumn == 0 && _currentLine == _imageData.Height) || bitStreamManager.EndOfStream)
                    {
                        finishDecode = true;
                    }
                }
            }

            UsedIndexes.Sort();
        }
Exemple #13
0
        public void Decode()
        {
            /* The compression used for the costume data is a simple byte based RLE compression.
             * However, it works by columns, not by lines.
             * Each byte contains the color in the high bits and the repetition count in the low bits.
             * If the repetition count is 0, then the next byte contains the actual repetition count.
             * How many bits are used for the color depends on the palette size: for a 16 color palette, 4 bits are used for the color; for 32 colors, 5 bits are used.
             */

            var bitStreamManager    = new BitStreamManager(_pictureData.ImageData);
            int colorSize           = 0;
            int repetitionCountSize = 0;

            if (_costume.PaletteSize == 16)
            {
                colorSize           = 4;
                repetitionCountSize = 4;
            }
            else
            {
                colorSize           = 5;
                repetitionCountSize = 3;
            }

            if (_pictureData.Width == 0 || _pictureData.Height == 0)
            {
                _resultBitmap = null;
                return;
            }

            _resultBitmap = new Bitmap(_pictureData.Width, _pictureData.Height);

            if (_pictureData.ImageData.Length == 0 ||
                (_pictureData.ImageData.Length == 1 && _pictureData.ImageData[0] == 0))
            {
                return;                                                                            //Algumas imagens são vazias!!
            }

            /*
             *  while(1)
             *        {
             *          rep = read_byte();
             *          color = rep >> shift;
             *          rep &= mask;
             *          if(!rep)
             *            rep = read_byte();
             *          while(rep > 0) {
             *            set_pixel(x,y,color);
             *            rep--;
             *            y++;
             *            if(y >= height) {
             *              y = 0;
             *              x++;
             *              if(x >= width) break;
             *            }
             *          }
             *        }
             *
             */
            bool finishDecode  = false;
            int  currentLine   = 0;
            int  currentColumn = 0;

            while (!finishDecode)
            {
                //if (currentColumn == _pictureData.Width -1 && currentLine == _pictureData.Height -1) Debugger.Break();

                int  repetitionCount = bitStreamManager.ReadValue(repetitionCountSize);
                byte paletteIndex    = bitStreamManager.ReadValue(colorSize);

                //The second conditiong wad added because of a bug when decoding DOTT, ROOM 65, Costume 001, Frame 7. This tweak solves.
                if (repetitionCount == 0 && bitStreamManager.Position != bitStreamManager.Lenght)
                {
                    repetitionCount = bitStreamManager.ReadByte();
                }

                SetCurrentColor(paletteIndex);
                for (int i = 0; i < repetitionCount; i++)
                {
                    _resultBitmap.SetPixel(currentColumn, currentLine, _currentColor);
                    currentLine++;
                    if (currentLine == _pictureData.Height)
                    {
                        currentLine = 0;
                        currentColumn++;
                    }
                }
                if ((currentColumn == _pictureData.Width && currentLine == 0) || bitStreamManager.EndOfStream)
                {
                    finishDecode = true;
                }
            }
        }
Exemple #14
0
        private StripData EncodeCompressedMethod2()
        {
            var strip     = new StripData();
            var bitStream = new BitStreamManager();

            bool transparent;
            int  paletteSize;

            VerifyStrip(out transparent, out paletteSize, true);

            bool alternateCode = EncodeSettings == EncodeTypeSettings.Method2AlternateCode;

            strip.CodecId = (byte)(GetSubstractionCode(transparent, true, CompressionTypes.Method2, alternateCode) + paletteSize);
            if (strip.CompressionType == CompressionTypes.Unknow)
            {
                strip.CodecId = (byte)(GetSubstractionCode(transparent, true, CompressionTypes.Method2, !alternateCode) + paletteSize);
            }

            _renderdingDirection = strip.RenderdingDirection;
            _currentLocation.X   = 0;
            _currentLocation.Y   = 0;

            //Color currentColor = GetNextPixel(); //pq isso fica menos errado!?
            Color currentColor        = _imageToEncode.GetPixel(_currentOffset + 0, 0);
            int   currentPaletteIndex = FindTableIndex(currentColor);

            bitStream.AddByte((byte)currentPaletteIndex);

            byte accumulatedSameColor = 0;

            while (!(_currentLocation.X == 7 && _currentLocation.Y == (_height - 1)))
            {
                var newPaletteIndex = FindTableIndex(GetNextPixel());

                if (newPaletteIndex == currentPaletteIndex)
                {
                    accumulatedSameColor++; //Add one to the count of pixels with the same color.
                    if (accumulatedSameColor == 255)
                    {
                        //If we have pixels with the previous color drawed before the color change
                        //We need to write that information to the data, before process the new color.
                        WriteAccumulatedColor(bitStream, accumulatedSameColor);
                        accumulatedSameColor = 0;
                    }
                }
                else
                {
                    if (accumulatedSameColor > 0)
                    {
                        //If we have pixels with the previous color drawed before the color change
                        //We need to write that information to the data, before process the new color.
                        WriteAccumulatedColor(bitStream, accumulatedSameColor);
                        accumulatedSameColor = 0;
                    }


                    /*
                     * Then discory the new bit code.
                     *
                     * 10: Read a new palette index from the bitstream (i.e., the number of bits specified by the parameter), and draw the next pixel.
                     * 11: Read the next 3 bit value, and perform an action, depending on the value:
                     *     000 (0): Decrease current palette index by 4.
                     *     001 (1): Decrease current palette index by 3.
                     *     010 (2): Decrease current palette index by 2.
                     *     011 (3): Decrease current palette index by 1.
                     *     100 (4): Read next 8 bits. Draw the number of pixels specified by these 8 bits with the current palette index (somewhat similar to RLE).
                     *     101 (5): Increase current palette index by 1.
                     *     110 (6): Increase current palette index by 2.
                     *     111 (7): Increase current palette index by 3.
                     */

                    bitStream.AddBit(true); //Add the change action bit

                    if ((newPaletteIndex < (currentPaletteIndex - 4)) || (newPaletteIndex > (currentPaletteIndex + 3)))
                    {
                        //reset the negation value, read the next index from the palette,
                        //and draw the pixel.
                        bitStream.AddBit(false);
                        bitStream.AddByte((byte)newPaletteIndex, paletteSize);
                    }
                    else
                    {
                        //Add the read code bit
                        bitStream.AddBit(true);
                        if (newPaletteIndex == (currentPaletteIndex - 4)) //000 (0): Decrease current palette index by 4.
                        {
                            //Add the code 0
                            bitStream.AddByte(0, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex - 3)) //001 (1): Decrease current palette index by 3.
                        {
                            //Add the code 1
                            bitStream.AddByte(1, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex - 2)) //010 (2): Decrease current palette index by 2.
                        {
                            //Add the code 2
                            bitStream.AddByte(2, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex - 1)) //011 (3): Decrease current palette index by 1.
                        {
                            //Add the code 3
                            bitStream.AddByte(3, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex + 1)) //101 (5): Increase current palette index by 1.
                        {
                            //Add the code 5
                            bitStream.AddByte(5, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex + 2)) //110 (6): Increase current palette index by 2.
                        {
                            //Add the code 6
                            bitStream.AddByte(6, 3);
                        }
                        else if (newPaletteIndex == (currentPaletteIndex + 3)) //111 (7): Increase current palette index by 3.
                        {
                            //Add the code 7
                            bitStream.AddByte(7, 3);
                        }
                        else
                        {
                            throw new ImageEncodeException("nao podia ter caido aqui");
                        }
                    }

                    currentPaletteIndex = newPaletteIndex;
                }
            }

            //if the loop terminated with accumulated bits pending, add these to the stream.
            if (accumulatedSameColor > 0)
            {
                //If we have pixels with the previous color drawed before the color change
                //We need to write that information to the data, before process the new color.
                WriteAccumulatedColor(bitStream, accumulatedSameColor);
            }

            strip.ImageData = bitStream.ToByteArray();
            return(strip);
        }
Exemple #15
0
        private StripData EncodeCompressedMethod1(bool horizontalDirection)
        {
            var strip     = new StripData();
            var bitStream = new BitStreamManager();

            bool transparent;
            int  paletteSize;

            VerifyStrip(out transparent, out paletteSize, true);

            strip.CodecId = (byte)(GetSubstractionCode(transparent, horizontalDirection, CompressionTypes.Method1) + paletteSize);

            _renderdingDirection = strip.RenderdingDirection;
            _currentLocation.X   = 0;
            _currentLocation.Y   = 0;

            int negationValue = 1;

            //Color currentColor = GetNextPixel(); //pq isso fica menos errado!?
            Color currentColor        = _imageToEncode.GetPixel(_currentOffset + 0, 0);
            int   currentPaletteIndex = FindTableIndex(currentColor);

            bitStream.AddByte((byte)currentPaletteIndex);


            while (!(_currentLocation.X == 7 && _currentLocation.Y == (_height - 1)))
            {
                var newPaletteIndex = FindTableIndex(GetNextPixel());

                if (newPaletteIndex == currentPaletteIndex)
                {
                    bitStream.AddBit(false); //continue Drawing the same color.
                }
                else
                {
                    bitStream.AddBit(true); //discover what to do.

                    if (newPaletteIndex == (currentPaletteIndex - negationValue))
                    {
                        //subtract the negation value from the palette and draw the next pixel;
                        bitStream.AddBit(true);
                        bitStream.AddBit(false);
                    }
                    else if (newPaletteIndex == (currentPaletteIndex - (negationValue * -1)))
                    {
                        //invert the negation value, subtract it from the palette
                        //and draw the next pixel;
                        negationValue *= -1;
                        bitStream.AddBit(true);
                        bitStream.AddBit(true);
                    }
                    else
                    {
                        //reset the negation value, read the next index from the palette,
                        //and draw the pixel.
                        negationValue = 1;
                        bitStream.AddBit(false);
                        bitStream.AddByte((byte)newPaletteIndex, paletteSize);
                    }

                    currentPaletteIndex = newPaletteIndex;
                }
            }

            strip.ImageData = bitStream.ToByteArray();
            return(strip);
        }
Exemple #16
0
        private void Encode()
        {
            if (_imageToEncode.Width != _pictureData.Width || _imageToEncode.Height != _pictureData.Height)
            {
                throw new ImageEncodeException("The image must have the same size as original costume frame");
            }

            var bitStreamManager        = new BitStreamManager();
            int colorSize               = 0;
            int repetitionCountSize     = 0;
            int maxRepetitionCountValue = 0;

            if (_costume.PaletteSize == 16)
            {
                colorSize               = 4;
                repetitionCountSize     = 4;
                maxRepetitionCountValue = 15; //1111
            }
            else
            {
                colorSize               = 5;
                repetitionCountSize     = 3;
                maxRepetitionCountValue = 7; //111
            }

            int currentLine   = 0;
            int currentColumn = 0;

            Color currentColor        = _imageToEncode.GetPixel(0, 0);
            byte  currentColorPalette = GetRelativePaletteIndex(currentColor);
            int   repetitionCount     = 0;

            /* The compression used for the costume data is a simple byte based RLE compression.
             * However, it works by columns, not by lines.
             * Each byte contains the color in the high bits and the repetition count in the low bits.
             * If the repetition count is 0, then the next byte contains the actual repetition count.
             * How many bits are used for the color depends on the palette size: for a 16 color palette, 4 bits are used for the color; for 32 colors, 5 bits are used.
             */
            while (!(currentLine == 0 && currentColumn == _pictureData.Width))
            {
                Color newColor = _imageToEncode.GetPixel(currentColumn, currentLine);
                if (newColor == currentColor)
                {
                    repetitionCount++;
                }
                else
                {
                    while (repetitionCount > 255)
                    {
                        //write the repetition count in the next byte
                        bitStreamManager.AddByte(0, repetitionCountSize);
                        bitStreamManager.AddByte(currentColorPalette, colorSize);
                        bitStreamManager.AddByte(255);
                        repetitionCount -= 255;
                    }

                    if (repetitionCount > maxRepetitionCountValue)
                    {
                        //write the repetition count in the next byte
                        bitStreamManager.AddByte(0, repetitionCountSize);
                        bitStreamManager.AddByte(currentColorPalette, colorSize);

                        bitStreamManager.AddByte((byte)repetitionCount);
                    }
                    else
                    {
                        bitStreamManager.AddByte((byte)repetitionCount, repetitionCountSize);
                        bitStreamManager.AddByte(currentColorPalette, colorSize);
                    }
                    currentColor        = newColor;
                    currentColorPalette = GetRelativePaletteIndex(currentColor);

                    repetitionCount = 1;
                }

                currentLine++;
                if (currentLine == _pictureData.Height)
                {
                    currentLine = 0;
                    currentColumn++;
                }
            }

            if (repetitionCount > 0)
            {
                while (repetitionCount > 255)
                {
                    //write the repetition count in the next byte
                    bitStreamManager.AddByte(0, repetitionCountSize);
                    bitStreamManager.AddByte(currentColorPalette, colorSize);
                    bitStreamManager.AddByte(255);
                    repetitionCount -= 255;
                }

                if (repetitionCount > maxRepetitionCountValue)
                {
                    //write the repetition count in the next byte
                    bitStreamManager.AddByte(0, repetitionCountSize);
                    bitStreamManager.AddByte(currentColorPalette, colorSize);

                    bitStreamManager.AddByte((byte)repetitionCount);
                }
                else
                {
                    bitStreamManager.AddByte((byte)repetitionCount, repetitionCountSize);
                    bitStreamManager.AddByte(currentColorPalette, colorSize);
                }
            }


            _pictureData.ImageData = bitStreamManager.ToByteArray();
        }
Exemple #17
0
        private ZPlaneStripData EncodeZPlaneStrip()
        {
            var strip     = new ZPlaneStripData();
            var bitStream = new BitStreamManager();

            var linesInformation = new List <LineInformation>();

            _currentLine = 0;
            var currentLineInformation = new LineInformation();

            byte lastLine = GetNextLine();

            if (lastLine == PeekNextLine())
            {
                currentLineInformation.RepeatSameLine = true;
            }

            currentLineInformation.Lines.Add(lastLine);

            //Primeira passagem - Cadastra tudo alternado
            while (_currentLine < (_height))
            {
                byte currentLine = GetNextLine();

                if (currentLine != lastLine)
                {
                    if (currentLineInformation.RepeatSameLine)
                    {
                        //Mudou de REPETIR para NÃO REPETIR
                        linesInformation.Add(currentLineInformation);

                        currentLineInformation = new LineInformation();
                        currentLineInformation.RepeatSameLine = false;
                    }
                }
                else
                {
                    if (!currentLineInformation.RepeatSameLine)
                    {
                        //Mudou de NÃO REPETIR para REPETIR
                        linesInformation.Add(currentLineInformation);

                        currentLineInformation = new LineInformation();
                        currentLineInformation.RepeatSameLine = true;
                    }
                }

                currentLineInformation.Lines.Add(currentLine);

                lastLine = currentLine;
            }
            linesInformation.Add(currentLineInformation);

            //Segunda passagem - verifica a lista de itens não repetidos para ver se o ultimo elemento é um elemento da lista repetida seguinte.
            for (int i = 1; i < linesInformation.Count; i++)
            {
                var previous          = linesInformation[i - 1];
                var previousLastIndex = previous.Lines.Count - 1;
                var current           = linesInformation[i - 1];

                if (!previous.RepeatSameLine && current.RepeatSameLine && previous.Lines[previousLastIndex] == current.Lines[0])
                {
                    //move o item da lista anterior para a lista atual
                    current.Lines.Insert(0, previous.Lines[previousLastIndex]);

                    previous.Lines.RemoveAt(previousLastIndex);
                }
            }

            //Terceira passagem - procura por listas que eventualmente ficaram vazias, e as remove.
            //É importante percorrer a lista ao contrários, caso contrário a lista sera lida errada, além de dar IndexOutOfBounds no final.
            for (int i = linesInformation.Count - 1; i >= 0; i--)
            {
                if (linesInformation[i].Lines.Count == 0)
                {
                    linesInformation.RemoveAt(i);
                }
            }

            //Quarta passagem, divide as listas com mais de 127 itens em varias listas, pois 127 é o limite máximo de 7 bits.
            var finalLinesInformation = new List <LineInformation>();

            foreach (LineInformation lineInformation in linesInformation)
            {
                if (lineInformation.Lines.Count > 127)
                {
                    while (lineInformation.Lines.Count > 127)
                    {
                        var dividedLineInformation = new LineInformation();
                        dividedLineInformation.RepeatSameLine = lineInformation.RepeatSameLine;
                        dividedLineInformation.Lines.AddRange(lineInformation.Lines.Take(127).ToArray());

                        finalLinesInformation.Add(dividedLineInformation);

                        lineInformation.Lines = lineInformation.Lines.Skip(127).ToList();
                    }
                }

                finalLinesInformation.Add(lineInformation);
            }

            //Quinta passagem, grava o BitStream.
            foreach (LineInformation lineInformation in finalLinesInformation)
            {
                if (lineInformation.RepeatSameLine)
                {
                    byte repeatByte = BinaryHelper.Compose2Bytes(1, (byte)lineInformation.Lines.Count, 7);
                    bitStream.AddByte(repeatByte);
                    bitStream.AddByte(lineInformation.Lines[0]);
                }
                else
                {
                    //Verifica se o different line não tinha apenas 1 linha antes de gravar a informação, isso pode acontecer
                    //em situações onde a linha 1 e 2 são A e 3 e 4 são B, por exemplo.
                    byte repeatByte = BinaryHelper.Compose2Bytes(0, (byte)lineInformation.Lines.Count, 7);
                    bitStream.AddByte(repeatByte);
                    foreach (byte differentLine in lineInformation.Lines)
                    {
                        bitStream.AddByte(differentLine);
                    }
                }
            }

            strip.ImageData = bitStream.ToByteArray();
            return(strip);
        }