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()); }
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); } } }
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]); }
// 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(); }
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); }
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); }