//Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBitwise Decompress(BitStreamFIFO inBits, AccessibleBitmapBitwise inBitmap, out BitStreamFIFO restBits, int bitLayer)
        {
            //Read necessary info from BitStream
            bool        currentVal = inBits.ReadBool();
            Queue <int> runs       = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref inBits));

            int pixelsToGo = runs.Dequeue() + 1;

            //Iterate trough all pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //Set the bit of the current pixel to the value of the current run
                    inBitmap.SetPixelBit(x, y, bitLayer, currentVal);

                    //Decrease the length of the current run & check if the end has bin reached
                    pixelsToGo--;
                    if (pixelsToGo == 0 && (x * y != (inBitmap.height - 1) * (inBitmap.width - 1)))
                    {
                        //Read the new run length from the BitStream & reverse the run bit
                        pixelsToGo = runs.Dequeue() + 1;

                        //Toggle bit value
                        currentVal = !currentVal;
                    }
                }
            }

            //Return rest of bits & return bitmap
            restBits = inBits;
            return(inBitmap);
        }
Пример #2
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBytewise Decompress(byte[] inBytes, AccessibleBitmapBytewise inBitmap, out byte[] restBytes, int byteLayer)
        {
            //Create a BitStreamFIFO class from the incoming bytes, becouse the decompressor for integer arrays uses it
            BitStreamFIFO layerBits = new BitStreamFIFO(inBytes);

            //Decompress the incoming data to an array of integers
            int[] layerByteArray = VaryingIntArrayCompressor.Decompress(ref layerBits);


            //Add the data from the array of integers to the incoming bitmap

            //Loop trough all lines of pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //Write the integer of this channel from the correct position in the input array to the current pixel
                    inBitmap.SetPixelByte(x, y, byteLayer, (byte)layerByteArray[y * inBitmap.width + x]);
                }
            }

            //Remove the bytes used for this channel from the incoming byte array and pass the rest of them to the next channel
            restBytes = new byte[layerBits.Length / 8];
            Array.Copy(inBytes, inBytes.Length - restBytes.Length, restBytes, 0, restBytes.Length);

            //Return the modified bitmap so the rest of the channels can be added to complete it
            return(inBitmap);
        }
Пример #3
0
        //Decompress BitStream into integer array
        public static int[] Decompress(ref BitStreamFIFO source)
        {
            //Read necessary info for decompression
            int compressionType  = source.ReadInt(2);                //The compression technique used
            int lengthSaveLength = source.ReadInt(6) * 8;            //The amount of bits needed to save the total length in bits of the compressed data
            int arrayDataLength  = source.ReadInt(lengthSaveLength); //The total length in bits of the compressed data

            //Create a new BitStream of correct length from the incoming BitStream
            BitStreamFIFO arrayData = new BitStreamFIFO(source.ReadBoolArray(arrayDataLength));

            //Decompress using the correct compression type
            int[] intArray = new int[0];
            switch (compressionType)
            {
            //Huffmann
            case 0:
                intArray = HuffmanIntArrayCompressor.DeCompress(arrayData);
                break;

            //Variable int length
            case 1:
                intArray = VaryingIntLengthIntArrayCompressor.Decompress(arrayData);
                break;

                //To add a compression technique, add a new case like the existing ones and increase the length of new byte[??][]
            }

            //Return the decompressed array of integers
            return(intArray);
        }
Пример #4
0
        public static int[] DeCompress(BitStreamFIFO source)
        {
            //dictionary decompile
            //1: add '0' to end
            //2: read byte; attach current code to byte; remove al '1' from end; replace last '0' with '1'
            int minBits          = source.ReadByte();
            int dictionaryLength = source.ReadInt(minBits) + 1;
            //Console.WriteLine(minBits + " " + dictionaryLength);
            SortedDictionary <string, int> dictionary = new SortedDictionary <string, int>();
            List <int>    dicNumbers = new List <int>();
            List <bool[]> dicCodes   = new List <bool[]>();
            string        tmpCode    = "";

            while (dictionary.Count < dictionaryLength)
            {
                if (source.ReadBool())
                {
                    tmpCode += "1";
                }
                else
                {
                    dictionary.Add(tmpCode, source.ReadInt(minBits));

                    if (tmpCode.Contains('1'))
                    {
                        while (tmpCode.Last() == '0')
                        {
                            tmpCode = tmpCode.Remove(tmpCode.Length - 1, 1);
                        }
                        tmpCode  = tmpCode.Remove(tmpCode.Length - 1, 1);
                        tmpCode += '0';
                    }
                }
            }

            /*for(int i = 0; i < dicNumbers.Count; i++)
             * {
             *  Console.WriteLine(dicNumbers[i] + " " + BoolArrString(dicCodes[i]));
             * }
             * Console.WriteLine();*/

            List <int> outputList = new List <int>();
            string     tmpRead    = "";

            while (source.Length > 0)
            {
                tmpRead += source.ReadBool()?'1':'0';
                int foundVal = 0;
                if (dictionary.TryGetValue(tmpRead, out foundVal))
                {
                    outputList.Add(foundVal);
                    tmpRead = "";
                }
            }

            return(outputList.ToArray());
        }
Пример #5
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmap Decompress(byte[] source, int width, int height, int pixelBytes)
        {
            //Create a BitStream from the input bytes becouse the decompress functions need this as input
            BitStreamFIFO bitStream = new BitStreamFIFO(source);

            //Create an empty bitmap with the correct dimensions, where the decompressed pixels will be written to
            AccessibleBitmap aBitmap = new AccessibleBitmap(width, height, pixelBytes);

            //Decompress the BitStream to a queue of integers for the lengths
            Queue <int> pixels = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref bitStream));

            //Decompress the BitStream to a queue of integers for the pixel values
            Queue <int> runs = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref bitStream));

            //Initialize
            int pixelsToGo = runs.Dequeue() + 1;        //The amount of pixels that should be written before the next run starts

            byte[] currentPixel = new byte[pixelBytes]; //The pixel value of the current run: initialize with the correct amount of channels

            //Loop trough all channels in the pixel of the current length
            for (int i = 0; i < pixelBytes; i++)
            {
                //Take a byte from the queue of pixel values to put in the current channel
                currentPixel[i] = (byte)pixels.Dequeue();
            }

            //Loop trough all lines of pixels
            for (int y = 0; y < height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < width; x++)
                {
                    //Set the bit of the current pixel to the value of the current run
                    aBitmap.SetPixel(x, y, currentPixel);

                    //Decrease the length of the current run
                    pixelsToGo--;

                    //If the end of the run has been reached
                    if (pixelsToGo == 0 && (x * y != (height - 1) * (width - 1)))
                    {
                        //Read the new run length from the BitStream
                        pixelsToGo = runs.Dequeue() + 1;

                        //Loop trough all channels in the pixel of the current length
                        for (int i = 0; i < pixelBytes; i++)
                        {
                            //Take a byte from the queue of pixel values to put in the current channel
                            currentPixel[i] = (byte)pixels.Dequeue();
                        }
                    }
                }
            }

            //Return the image as aBitmap
            return(aBitmap);
        }
Пример #6
0
            public static BitStreamFIFO Merge(BitStreamFIFO bitStream1, BitStreamFIFO bitStream2)
            {
                int newLength = bitStream1.Length + bitStream2.Length;

                bool[] mergedBools = new bool[newLength];
                Array.Copy(bitStream1.ToBoolArray(), bitStream1.readIndex, mergedBools, 0, bitStream1.Length);
                Array.Copy(bitStream2.ToBoolArray(), bitStream2.readIndex, mergedBools, bitStream1.Length, bitStream2.Length);

                return(new BitStreamFIFO(mergedBools));
            }
Пример #7
0
        //Compress integer array into BitStream
        public static BitStreamFIFO Compress(int[] source)
        {
            //Compress the array of integers using all different compression techniques, where possible at the same time
            BitStreamFIFO[] compressionTechniques = new BitStreamFIFO[2];
            Parallel.For(0, compressionTechniques.Length, (i, state) =>
            {
                switch (i)
                {
                //Huffmann: generate a dictionary of all used integer values where more frequent values have a code with less bits
                case 0:
                    compressionTechniques[i] = HuffmanIntArrayCompressor.Compress(source);
                    break;

                //Variable int length: save smaller integers with less bits than bigger integers
                case 1:
                    compressionTechniques[i] = VaryingIntLengthIntArrayCompressor.Compress(source);
                    break;

                    //To add a compression technique, add a new case like the existing ones and increase the length of new byte[??][]
                }
            });

            //Choose the smallest compression type

            //Initialize
            int smallestID   = 0;               //The ID of the smallest compression type
            int smallestSize = int.MaxValue;    //The size ofthe smallest compression type: int.MaxValue is assigned to make sure that the first compression to be checked will be smaaller than this value

            //Loop trough all saved compression techniques
            for (int i = 0; i < compressionTechniques.Length; i++)
            {
                //If the current technique is smaller than the smallest technique which has been checked
                if (compressionTechniques[i].Length < smallestSize)
                {
                    //Mark this technique as smallest
                    smallestSize = compressionTechniques[i].Length;
                    smallestID   = i;
                }
            }

            //Create a new BitStream to write necessary information for the decompressor
            BitStreamFIFO compressionInfo = new BitStreamFIFO();

            //Calculate the amount of bits needed to save the total length in bits of the compressed data
            int lengthSaveLength = (int)Math.Ceiling(Math.Log(smallestSize, 2) / 8);

            //Write data to the compression info
            compressionInfo.Write(smallestID, 2);                       //The compression technique used
            compressionInfo.Write(lengthSaveLength, 6);                 //The amount of bits needed to save the total length in bits of the compressed data
            compressionInfo.Write(smallestSize, lengthSaveLength * 8);  //The total length in bits of the compressed data

            //Merge the info about the compression type with the compressed data & return
            return(BitStreamFIFO.Merge(compressionInfo, compressionTechniques[smallestID]));
        }
Пример #8
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmap Decompress(byte[] source, int width, int height, int pixelBytes)
        {
            BitStreamFIFO layerBits = new BitStreamFIFO(source);

            int[] byteArray = VaryingIntArrayCompressor.Decompress(ref layerBits);

            //Create aBitmap from pixel data
            AccessibleBitmap aBitmap = new AccessibleBitmap(width, height, pixelBytes);

            aBitmap.SetRawPixelBytes(Array.ConvertAll(byteArray, Convert.ToByte));

            return(aBitmap);
        }
Пример #9
0
        //Compress aBitmap into byte array
        public static byte[] Compress(AccessibleBitmap source)
        {
            //Initialize
            List <int> distances    = new List <int>(); //A list containing all the lenghts of same pixels
            List <int> pixels       = new List <int>(); //A list containing all the pixels that correspond to the lengths in 'distances' list
            int        tempDistance = -1;               //The length of one run of bits with the same value, while it is not saved yet: -1 because it will be increased before the first check

            byte[] lastPixel = source.GetPixel(0, 0);   //The pixel of the last checked pixel, to compare with the current pixel: set value to the value of the first pixel so the first check will succeed

            //Loop trough all lines of pixels
            for (int y = 0; y < source.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < source.width; x++)
                {
                    //Take value of the current pixel
                    byte[] currentPixel = source.GetPixel(x, y);

                    //If the value of the bit of this pixel matches the value of the bit of the previous pixel
                    if (currentPixel.SequenceEqual(lastPixel))
                    {
                        //Values are the same, so increase current run
                        tempDistance++;
                    }
                    else
                    {
                        //Values are not the same, so save the run
                        distances.Add(tempDistance);
                        pixels.AddRange(Array.ConvertAll(lastPixel, b => (int)b));

                        //Set the bit value for the next comparison to the bit value of this pixel
                        lastPixel = currentPixel;

                        //Reset the run length for the new run
                        tempDistance = 0;
                    }
                }
            }
            //Save the last run becouse this never happens in the loop
            distances.Add(tempDistance);
            pixels.AddRange(Array.ConvertAll(lastPixel, b => (int)b));

            //Compress the array of run lengths using different techniques
            BitStreamFIFO pixelStream = VaryingIntArrayCompressor.Compress(pixels.ToArray());

            //Compress the array of run lengths using different techniques
            BitStreamFIFO lengthStream = VaryingIntArrayCompressor.Compress(distances.ToArray());

            //Combine the compressed data of the runs with the compressed data of the pixel values, then return the BitStream
            return(BitStreamFIFO.Merge(pixelStream, lengthStream).ToByteArray());
        }
Пример #10
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBytewise Decompress(byte[] inBytes, AccessibleBitmapBytewise inBitmap, out byte[] restBytes, int byteLayer)
        {
            //Create a AccessibleBitmapbitwise class from the incoming AccessibleBitmapbytewise class, for better access to individual bits
            AccessibleBitmapBitwise outputBitmap = new AccessibleBitmapBitwise(inBitmap);

            //Create a BitStreamFIFO class from the incoming bytes, to feed into the decompression algorithms
            BitStreamFIFO bitStream = new BitStreamFIFO(inBytes);

            //Loop trough all bit layers of current byte layer
            for (int i = byteLayer * 8; i < byteLayer * 8 + 8; i++)
            {
                //Read compression type as a 3-bit integer
                int compressionType = bitStream.ReadInt(3);

                //Decompress using the correct compression type
                switch (compressionType)
                {
                //Uncompressed
                case 0:
                    outputBitmap = UncompressedBitmapCompressorBitwise.Decompress(bitStream, outputBitmap, out bitStream, i);
                    break;

                //Bit channel compressed as 8-bit integers
                case 1:
                    outputBitmap = ByteArrayCompressorBitwise.Decompress(bitStream, outputBitmap, out bitStream, i);
                    break;

                //Run length encoding
                case 2:
                    outputBitmap = RunLengthEncodingCompressorBitwise.Decompress(bitStream, outputBitmap, out bitStream, i);
                    break;

                //Run length encoding vertical
                case 3:
                    outputBitmap = RunLengthEncodingCompressorVerticalBitwise.Decompress(bitStream, outputBitmap, out bitStream, i);
                    break;

                //To add a decompression type add a new case like the existing ones

                //Unknown compression type: error
                default:
                    throw new Exception("Unexisting compression type");
                }
            }
            //Remove the bytes used for this channel from the incoming byte array and pass the rest of them to the next channel
            restBytes = new byte[bitStream.Length / 8];
            Array.Copy(inBytes, inBytes.Length - (bitStream.Length / 8), restBytes, 0, restBytes.Length);

            //Return the modified bitmap as AccessibleBitmapbytewise so the rest of the channels can be added to complete it
            return(new AccessibleBitmapBytewise(outputBitmap.GetAccessibleBitmap()));
        }
        //Compress aBitmap into byte array
        public static BitStreamFIFO Compress(AccessibleBitmapBitwise source, int bitLayer)
        {
            //Initialize
            List <int> distances    = new List <int>();                   //A list containing all the lenghts of same bits
            int        tempDistance = -1;                                 //The length of one run of bits with the same value, while it is not saved yet: -1 becouse it will be increased before the first check
            bool       lastVal      = source.GetPixelBit(0, 0, bitLayer); //The bit value of the last checked pixel, to compare with the current pixel: set value to the value of the first pixel so the first check will succeed

            //Loop trough all lines of pixels
            for (int y = 0; y < source.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < source.width; x++)
                {
                    //Take value of the current pixel
                    bool currentBool = source.GetPixelBit(x, y, bitLayer);

                    //If the value of the bit of this pixel matches the value of the bit of the previous pixel
                    if (currentBool == lastVal)
                    {
                        //Values are the same, so increase current run
                        tempDistance++;
                    }
                    else
                    {
                        //Values are not the same, so save the run
                        distances.Add(tempDistance);

                        //Set the bit value for the next comparison to the bit value of this pixel
                        lastVal = currentBool;

                        //Reset the run length for the new run
                        tempDistance = 0;
                    }
                }
            }
            //Save the last run becouse this never happens in the loop
            distances.Add(tempDistance);

            //Save the bit value of the first pixel, because the decompressor needs to know this
            bool initialVal = source.GetPixelBit(0, 0, bitLayer);

            //Compress the array of run lengths using different techniques
            BitStreamFIFO bitStream = VaryingIntArrayCompressor.Compress(distances.ToArray());

            //Combine the inititial bit value with the compressed data of the runs, then return the BitStream
            return(BitStreamFIFO.Merge(new BitStreamFIFO(new bool[] { initialVal }), bitStream));
        }
Пример #12
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBitwise Decompress(BitStreamFIFO inBits, AccessibleBitmapBitwise inBitmap, out BitStreamFIFO restBits, int bitLayer)
        {
            //Decompress the incoming data to an array of integers
            int[] ints = VaryingIntArrayCompressor.Decompress(ref inBits);

            //Initialize
            int intIndex = 0;               //The index in the array of intergers, from where the next integer should be taken

            bool[] tmpBools  = new bool[8]; //The array of bits from which bits will be read to be applied to pixels
            int    boolIndex = 8;           //The index in the array of bits, from where the next bit should be taken


            //Add the data from the array of integers to the incoming bitmap

            //Loop trough all lines of pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //If index is 8, all bits are used, so tmpBools should be renewed by using the next integer in the array of integers
                    if (boolIndex == 8)
                    {
                        //Reset the index to 0, so the next bit will be read from the start
                        boolIndex = 0;

                        //Convert the next integer in the array to a bool array, and write it to tmpBools
                        tmpBools = new BitStreamFIFO().IntToBoolArray(ints[intIndex], 8);

                        //Increase the index of the integer array, so the next integer will be read correctly
                        intIndex++;
                    }

                    //Write the bit of this channel from the correct position in the array of bits to the current pixel
                    inBitmap.SetPixelBit(x, y, bitLayer, tmpBools[boolIndex]);

                    //Increase index for next bit
                    boolIndex++;
                }
            }

            //Set the output BitStream to the remaining bits of the input BitStream
            restBits = inBits;

            //Return the modified AccessibleBitmapBitwise so the rest of the channels can be added to complete it
            return(inBitmap);
        }
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBytewise Decompress(byte[] inBytes, AccessibleBitmapBytewise inBitmap, out byte[] restBytes, int byteLayer)
        {
            //Create a BitStream from the input bytes becouse the decompress functions need this as input
            BitStreamFIFO bitStream = new BitStreamFIFO(inBytes);

            //Decompress the BitStream to a queue of integers for the lengths
            Queue <int> pixels = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref bitStream));

            //Decompress the BitStream to a queue of integers for the pixel values
            Queue <int> runs = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref bitStream));

            //Initialize
            int  pixelsToGo   = runs.Dequeue() + 1;     //The amount of pixels that should be written before the next run starts
            byte currentPixel = (byte)pixels.Dequeue(); //The pixel value of the current run: initialize with the first pixel value

            //Loop trough all lines of pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //Set the bit of the current pixel to the value of the current run
                    inBitmap.SetPixelByte(x, y, byteLayer, currentPixel);

                    //Decrease the length of the current run
                    pixelsToGo--;

                    //If the end of the run has been reached
                    if (pixelsToGo == 0 && (x * y != (inBitmap.height - 1) * (inBitmap.width - 1)))
                    {
                        //Read the new run length from the BitStream
                        pixelsToGo = runs.Dequeue() + 1;

                        //Take a byte from the queue of pixel values to put in the current channel
                        currentPixel = (byte)pixels.Dequeue();
                    }
                }
            }

            //Remove the bytes used for this channel from the incoming byte array and pass the rest of them to the next channel
            restBytes = new byte[bitStream.Length / 8];
            Array.Copy(inBytes, inBytes.Length - restBytes.Length, restBytes, 0, restBytes.Length);

            //Return the image as aBitmap
            return(inBitmap);
        }
Пример #14
0
        public TreeWalker(int[] sortedNumbers, int[][] treeInts)
        {
            sortednumbers = sortedNumbers;
            treeints      = treeInts;

            numberVals = new bool[sortedNumbers.Length][];
            minBits    = (int)Math.Ceiling(Math.Log(sortedNumbers.Max() + 1, 2));
            minBits    = minBits < 1 ? 1 : minBits;

            outputStream = new BitStreamFIFO();
            outputStream.Write((byte)minBits);
            outputStream.Write(sortedNumbers.Length - 1, minBits);
            //Console.WriteLine(minBits + " " + sortedNumbers.Length);

            LoopTree(new bool[0], treeInts.Length - 1);
            //Console.WriteLine();
        }
Пример #15
0
        //Compress aBitmap into byte array
        public static BitStreamFIFO Compress(AccessibleBitmapBitwise source, int bitLayer)
        {
            //Initialize
            List <int> ints = new List <int>(); //List of all integers generated from the bits of this channel

            bool[] tmpBools = new bool[8];      //The collection of bits that will be converted to an interger
            int    index    = 0;                //The index in tmpBools where a new bit should be inserted

            //Loop trough all lines of pixels
            for (int y = 0; y < source.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < source.width; x++)
                {
                    //Write bit of current pixel to the correct position in tmpBools
                    tmpBools[index] = source.GetPixelBit(x, y, bitLayer);

                    //Increase index for next bit
                    index++;

                    //If index is 8, tmpBools is full
                    if (index == 8)
                    {
                        //Set index to 0, so the next bit will be written to the start
                        index = 0;

                        //Convert tmpBools to an integer & add the result to the list of integers
                        ints.Add(new BitStreamFIFO().BoolArrayToInt(tmpBools));
                    }
                }
            }

            //If index is not 0, it has not been reset at last, so tmpBools should be saved for the last bits it contains
            if (index > 0)
            {
                //Convert tmpBools to an integer & add the result to the list of integers
                ints.Add(new BitStreamFIFO().BoolArrayToInt(tmpBools));
            }

            //Compress the obtained array of integers using different techniques
            BitStreamFIFO bitStream = VaryingIntArrayCompressor.Compress(ints.ToArray());

            //Return the output array
            return(bitStream);
        }
Пример #16
0
        // This function is used to compress the image using the LZW algorithm
        public static byte[] Compress(AccessibleBitmap source)
        {
            // Add first 255 standard values to LZWDictionary in LZWCompressor.cs
            string[] LZWDictionary = new string[256];
            for (int i = 0; i < 256; i++)
            {
                LZWDictionary[i] = ((char)i).ToString();
            }

            List <string> dictionary     = new List <string>(LZWDictionary);            // Clone dictionary of all bytes
            Queue <byte>  bytes          = new Queue <byte>(source.GetRawPixelBytes()); // Get all bytes from the source image
            BitStreamFIFO bs             = new BitStreamFIFO();                         // Create bitstream for output
            int           maxDictSize    = (int)Math.Pow(2, maxBitCount);               // Get maximum dictionary size
            string        encodingString = ((char)bytes.Dequeue()).ToString();          // Create string to add encoding to

            while (bytes.Count > 0)
            {
                // Clear dict if full
                if (dictionary.Count >= maxDictSize)
                {
                    dictionary = new List <string>(LZWDictionary);
                }

                char b = (char)bytes.Dequeue();

                if (dictionary.Contains(encodingString + b))
                {
                    encodingString += b;
                }
                else
                {
                    bs.Write(dictionary.FindIndex(x => x.StartsWith(encodingString)), maxBitCount);
                    dictionary.Add(encodingString + b);
                    encodingString = b.ToString();
                }
            }

            // Write remaining byte to bitstream
            bs.Write(dictionary.FindIndex(x => x.StartsWith(encodingString)), maxBitCount);

            // Return the bitstream as byte array
            return(bs.ToByteArray());
        }
Пример #17
0
        //Compress aBitmap into byte array
        public static BitStreamFIFO Compress(AccessibleBitmapBitwise source, int bitLayer)
        {
            //Creates a new BitStreamFIFO object where all bits will be written to
            BitStreamFIFO bitStream = new BitStreamFIFO();

            //Loop trough all lines of pixels
            for (int y = 0; y < source.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < source.width; x++)
                {
                    //Write the bit of this channel from the current pixel to the output BitStream
                    bitStream.Write(source.GetPixelBit(x, y, bitLayer));
                }
            }

            //Return the BitStream
            return(bitStream);
        }
Пример #18
0
        public static AccessibleBitmap Decompress(byte[] source, int width, int height, int pixelBytes)
        {
            BitStreamFIFO bs = new BitStreamFIFO(source);                               // Convert the image into a bitstream
            bool verticallyCompressed = bs.ReadBool();                                  // Store if image was vertically compressed or not
            int maxBitCount = bs.ReadByte();                                            // Get the highest bitcount value
            AccessibleBitmap bmp = new AccessibleBitmap(width, height, pixelBytes);     // Create new bitmap to write all pixels to

            // Ints to keep track of coords
            int x = 0;
            int y = 0;

            // Loop while there are still bits to read
            while (bs.Length > maxBitCount)
            {
                int counterValue = bs.ReadInt(maxBitCount);     // Get the counter value of the next pixel value
                byte[] pixel = bs.ReadByteArray(pixelBytes);    // Get the pixel value

                for (int i = 0; i < counterValue; i++)
                {
                    bmp.SetPixel(x, y, pixel);
                    if (verticallyCompressed)
                    {
                        y++;
                        if (y >= height)
                        {
                            x++;
                            y = 0;
                        }
                    }else
                    {
                        x++;
                        if (x >= width)
                        {
                            y++;
                            x = 0;
                        }
                    }
                }
            }

            // Return the bitmap
            return bmp;
        }
        //Compress aBitmap into byte array
        public static BitStreamFIFO Compress(AccessibleBitmapBitwise source, int bitLayer)
        {
            //Initialize vars
            BitStreamFIFO bitStream    = new BitStreamFIFO();
            List <int>    distances    = new List <int>();
            int           tempDistance = -1;
            bool          lastVal      = source.GetPixelBit(0, 0, bitLayer);

            //Iterate trough pixels
            for (int y = 0; y < source.height; y++)
            {
                for (int x = 0; x < source.width; x++)
                {
                    //Take value of pixel & compare with previous value
                    bool currentBool = source.GetPixelBit(x, y, bitLayer);
                    if (currentBool == lastVal)
                    {
                        //Values are the same, so increase current run
                        tempDistance++;
                    }
                    else
                    {
                        //Values are not the same, so save the run and create a new one
                        distances.Add(tempDistance);
                        lastVal      = currentBool;
                        tempDistance = 0;
                    }
                }
            }
            //Save the last run becouse this never happens in the loop
            distances.Add(tempDistance);


            bool initialVal = source.GetPixelBit(0, 0, bitLayer);

            bitStream.Write(initialVal);

            BitStreamFIFO output = BitStreamFIFO.Merge(bitStream, VaryingIntArrayCompressor.Compress(distances.ToArray()));

            return(output);
        }
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBitwise Decompress(BitStreamFIFO inBits, AccessibleBitmapBitwise inBitmap, out BitStreamFIFO restBits, int bitLayer)
        {
            //Read necessary info from BitStream
            bool currentVal = inBits.ReadBool();    //The bit value of the first run

            //Decompress the BitStream to a queue of integers
            Queue <int> runs = new Queue <int>(VaryingIntArrayCompressor.Decompress(ref inBits));

            //Initialize
            int pixelsToGo = runs.Dequeue() + 1;    //The amount of pixels that should be written before the next run starts

            //Loop trough all lines of pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //Set the bit of the current pixel to the value of the current run
                    inBitmap.SetPixelBit(x, y, bitLayer, currentVal);

                    //Decrease the length of the current run
                    pixelsToGo--;

                    //If the end of the run has been reached
                    if (pixelsToGo == 0 && (x * y != (inBitmap.height - 1) * (inBitmap.width - 1)))
                    {
                        //Read the new run length from the BitStream
                        pixelsToGo = runs.Dequeue() + 1;

                        //Toggle bit value, because a bit can just have 2 values, and this run cannot have the same value as the previous run
                        currentVal = !currentVal;
                    }
                }
            }

            //Set the output BitStream to the remaining bits of the input BitStream
            restBits = inBits;

            //Return the modified AccessibleBitmapBitwise so the rest of the channels can be added to complete it
            return(inBitmap);
        }
Пример #21
0
        //Decompress byte array into aBitmap with help of width, length and bitdepth
        public static AccessibleBitmapBitwise Decompress(BitStreamFIFO inBits, AccessibleBitmapBitwise inBitmap, out BitStreamFIFO restBits, int bitLayer)
        {
            //Add the data from this stream to the incoming bitmap

            //Loop trough all lines of pixels
            for (int y = 0; y < inBitmap.height; y++)
            {
                //Loop trough all pixels in this line
                for (int x = 0; x < inBitmap.width; x++)
                {
                    //Write the bit of this channel from the input BitStream to the current pixel
                    inBitmap.SetPixelBit(x, y, bitLayer, inBits.ReadBool());
                }
            }

            //Set the output BitStream to the remainder of the input BitStream
            restBits = inBits;

            //Return the modified bitmap so the rest of the channels can be added to complete it
            return(inBitmap);
        }
Пример #22
0
        //Decompress BitStream into integer array
        public static int[] Decompress(BitStreamFIFO source)
        {
            //Read necessary info from BitStream
            int bitDepth = source.ReadByte();                   //The default bits to read values

            int[] specialValues = new int[source.ReadByte()];   //The amount of values that trigger an increase of bits to read

            //Read all values that trigger an increase of bits to read
            for (int i = 0; i < specialValues.Length; i++)
            {
                specialValues[i] = source.ReadInt(bitDepth);
            }

            //Create a list of ints as output
            List <int> outputList = new List <int>();

            //Read data while the input stream contains data
            while (source.Length >= bitDepth)
            {
                //Read an integer using the default amount of bits
                int tmpLengthTmp = source.ReadInt(bitDepth);

                //If the current value is a value that triggers an increase of bits to read
                if (specialValues.Contains(tmpLengthTmp))
                {
                    //Read a new value with the correct amount of bits
                    int extraLength = Array.IndexOf(specialValues, tmpLengthTmp) + 1;

                    //Replace the current value with the new value
                    tmpLengthTmp = source.ReadInt(bitDepth + extraLength);
                }

                //Add the current value to the output
                outputList.Add(tmpLengthTmp);
            }

            //Return output as an array of integers
            return(outputList.ToArray());
        }
Пример #23
0
        //Compress integer array into BitStream
        public static BitStreamFIFO Compress(int[] source)
        {
            //Get the amount of bits needed to store the longest run
            int invariableMinBits = (int)Math.Ceiling(Math.Log(source.Max() + 1, 2));

            invariableMinBits = invariableMinBits < 1 ? 1 : invariableMinBits;

            //Initialize
            List <int> nonExisting = new List <int>();  //Create a list to which all values that aren't present in the source array will be added
            int        minBits     = invariableMinBits; //The minimum amount of bits used for variable save bits, related to the list of nonexisting values

            //Loop trough all possible values within the range of the source values
            for (int i = 0; i < source.Max(); i++)
            {
                //If a value is not present in the source array
                if (!source.Contains(i))
                {
                    //Add current value to the list
                    nonExisting.Add(i);

                    //Set the minimum amount of bits to save this value
                    minBits = (int)Math.Ceiling(Math.Log(i + 1, 2));
                    minBits = minBits < 1 ? 1 : minBits;

                    //If the amount of unused values is equal to the difference between invariableMinBits and minBits
                    if (nonExisting.Count >= invariableMinBits - minBits)
                    {
                        //Minbits is now the smallest possible amount of bits in which the source array can be saved variable, so stop checking for more unused values
                        break;
                    }
                }
            }


            //Divide the source values in categories with the same minimum amount of bits to be saved in

            //Create all categories
            int[][] distancesByPower = new int[invariableMinBits][];

            //Loop trough all categories
            for (int i = 0; i < distancesByPower.Length; i++)
            {
                //Define the smalles and biggest value of the current category
                int minVal = (int)Math.Pow(2, i) - 1;
                int maxVal = (int)Math.Pow(2, i + 1);

                //Add all values within the specified range to this category
                distancesByPower[i] = new List <int>(source).FindAll(x => x < maxVal && x >= minVal).ToArray();
            }


            //Find out which possible minimum amount of bits used will compress the most

            //Initialize
            int chosenMinBits = invariableMinBits;  //The chosen minimum amount of bits
            int smallestSize  = int.MaxValue;       //The size of the compressed data when using the chosen minimum of bits

            //Loop trough all possible minimum amounts of bits
            for (int i = 0; i <= invariableMinBits - minBits; i++)
            {
                //Calculate the length of the current minimum amount of bits

                //Initialize
                int length   = 0;                       //The total length
                int baseBits = invariableMinBits - i;   //Define the current minimum amount of bits

                //Add the length of all data that will be saved in the minimum amount of bits to the length variable
                for (int j = 0; j < baseBits; j++)
                {
                    length += distancesByPower[j].Length * baseBits;
                }

                //Loop trough all data that needs more bits to be saved than the minimum
                for (int j = 0; j < i; j++)
                {
                    //Define the minimum bits for this value
                    int currentBits = invariableMinBits - j;

                    //Add the minimum bits of this value + the general minimum bits to the length variable, becouse an extra value should be used to indicate the extra amount of bits
                    length += distancesByPower[currentBits - 1].Length * (baseBits + currentBits);
                }

                //If the length of this minimum amount of bits is smaller than the chosen amount of bits
                if (length < smallestSize)
                {
                    //Set this smallest amount of bits as the chosen amount of bits
                    smallestSize  = length;
                    chosenMinBits = baseBits;
                }
            }


            //Create a new BitStream as output
            BitStreamFIFO bitStream = new BitStreamFIFO();

            //Write necessary info for decompressing to the output stream
            bitStream.Write((byte)chosenMinBits);                       //The chosen default bits to save values
            bitStream.Write((byte)(invariableMinBits - chosenMinBits)); //The amount of values that trigger an increase of bits per value

            //Write all values that trigger an increase of bits per value
            for (int i = 0; i < invariableMinBits - chosenMinBits; i++)
            {
                bitStream.Write(nonExisting[i], chosenMinBits);
            }


            //Write all values to the stream

            //Loop trough all values
            foreach (int i in source)
            {
                //Get the amount of extra bits needed to save this value
                int extraBits = 0;
                while (Math.Pow(2, chosenMinBits + extraBits) - 1 < i)
                {
                    extraBits++;
                }

                //Write trigger value to stream if extra bits are needed
                if (extraBits > 0)
                {
                    bitStream.Write(nonExisting[extraBits - 1], chosenMinBits);
                }

                //Write the value to the stream using the correct amount of bits
                bitStream.Write(i, chosenMinBits + extraBits);
            }

            //Return the compressed data
            return(bitStream);
        }
Пример #24
0
        public static byte[] CompressVertical(AccessibleBitmap source)
        {
            byte[] lastpixel = null;                                // Create variable to store the last pixel
            int colorCounter = 1;                                   // Create counter for current color
            BitStreamFIFO bs = new BitStreamFIFO();                 // Create new bitstream for all the bits
            int maxCount = 0;                                       // Create variable to store the max bitcount
            Queue<PixelArray> output = new Queue<PixelArray>();     // Create list to store all the pixelvalues in

            // Write one bit to the bitstream, so the decompressor knows to decompress vertically
            bs.Write(true);

            // Iterate through every vertical row
            for (int x = 0; x < source.width; x++)
            {
                // Iterate through every pixel in the vertical row
                for (int y = 0; y < source.height; y++)
                {
                    // Check if the variable lastpixel is empty
                    if (lastpixel == null)
                    {
                        // If lastpixel is empty, set last pixel to the first pixel
                        lastpixel = source.GetPixel(x, y);
                    }
                    else
                    {
                        // If lastpixel isn't empty, compare last pixel with new pixel
                        if (lastpixel.SequenceEqual(source.GetPixel(x, y)))
                        {
                            // Pixels matched, so increase the counter value
                            colorCounter++;
                        }
                        else
                        {
                            // If the pixels don't match, add the counter with the last pixel to the output queue
                            output.Enqueue(new PixelArray(colorCounter, lastpixel));
                            // Check if the new countervalue is higher then the last one, if so set maxBitCount to that
                            if (colorCounter > maxCount)
                                maxCount = colorCounter;

                            // Reset the colorCounter and set the last pixel to the new pixel
                            colorCounter = 1;
                            lastpixel = source.GetPixel(x, y);
                        }
                    }
                }
            }

            // Add the remaining pixel(s) to the bitstream
            output.Enqueue(new PixelArray(colorCounter, lastpixel));
            // Check if the new countervalue is higher then the last one, if so set maxBitCount to that
            if (colorCounter > maxCount)
                maxCount = colorCounter;

            // Write the maxCount to the bitstream
            bs.Write((byte)Math.Ceiling(Math.Log(maxCount, 2)));

            // Add all the pixels from the queue to the bitstream
            while (output.Count > 0)
            {
                PixelArray pixel = output.Dequeue();
                bs.Write(pixel.Count, (int)Math.Ceiling(Math.Log(maxCount, 2)));
                bs.Write(pixel.Pixel);
            }

            // Return the bitsream as a byte[]
            return bs.ToByteArray();
        }
Пример #25
0
        public static BitStreamFIFO Compress(int[] source)
        {
            List <int> numbers = new List <int>();
            List <int> weights = new List <int>();

            foreach (int b in source)
            {
                if (numbers.Contains(b))
                {
                    weights[numbers.IndexOf(b)]++;
                }
                else
                {
                    numbers.Add(b);
                    weights.Add(1);
                }
            }

            List <int> sortedWeightTmp = weights;

            sortedWeightTmp.Sort();
            int[] sortedWeightsInts = sortedWeightTmp.ToArray();
            int[] sortedNumbers     = new int[numbers.Count];
            int[] sortedWeights     = new int[weights.Count];
            for (int i = 0; i < sortedWeightTmp.Count; i++)
            {
                int oldIndex = weights.IndexOf(sortedWeightsInts[i]);
                sortedNumbers[i]  = numbers[oldIndex];
                sortedWeights[i]  = weights[oldIndex];
                weights[oldIndex] = 0;
            }

            /*for (int i = 0; i < sortedNumbers.Length; i++)
             * {
             *  Console.WriteLine(sortedNumbers[i] + "\t" + sortedWeights[i]);
             * }
             * Console.WriteLine();*/

            List <int[]> tree    = new List <int[]>();
            List <int[]> sources = new List <int[]>();

            for (int i = 0; i < sortedWeights.Length; i++)
            {
                sources.Add(new int[] { sortedWeights[i], -1, i });
            }

            while (sources.Count > 1)
            {
                tree.AddRange(sources.GetRange(0, 2));
                sources.RemoveRange(0, 2);
                sources.Add(new int[] { tree[tree.Count - 1][0] + tree[tree.Count - 2][0], tree.Count - 1, tree.Count - 2 });
                sources.Sort((s, t) => s[0] - t[0]);
            }
            tree.Add(sources[0]);

            Array.Reverse(sortedNumbers);
            TreeWalker    walker       = new TreeWalker(sortedNumbers, tree.ToArray());
            BitStreamFIFO outputStream = walker.outputStream;

            //Console.WriteLine("s" + outputStream.Length);
            bool[][] numberVals = walker.numberVals;

            /*int length = 0;
             * for (int i = 0; i < numberVals.Length; i++)
             * {
             *  Console.WriteLine(i + "\t" + sortedNumbers[i] + "\t" + sortedWeights[i] + "\t" + BoolArrString(numberVals[i]));
             *  length += sortedWeights[i] * numberVals[i].Length;
             * }*/
            //Console.WriteLine(source.Length);
            //Console.WriteLine(length);

            foreach (int i in source)
            {
                int index = Array.IndexOf(sortedNumbers, i);
                outputStream.Write(numberVals[index]);
                //Console.WriteLine(BoolArrString(numberVals[index]) + "\t" + i);
                //Console.WriteLine(i);
            }
            //Console.WriteLine(source.Length * 8);
            //Console.WriteLine("length"+outputStream.Length);
            return(outputStream);
        }
Пример #26
0
        //Compress aBitmap into byte array
        public static byte[] Compress(AccessibleBitmapBytewise source, int byteLayer)
        {
            //Loop trough all layers of bits, where possible at the same time
            AccessibleBitmapBitwise aBitmap = new AccessibleBitmapBitwise(source);

            BitStreamFIFO[] byteLayers = new BitStreamFIFO[8];
            Parallel.For(byteLayer * 8, byteLayer * 8 + 8, (z, state) => //for(int z = byteLayer * 8; z < byteLayer * 8 + 8; z++)
            {
                //Compress image using all different compression techniques, where possible at the same time
                BitStreamFIFO[] compressionTechniques = new BitStreamFIFO[4];
                Parallel.For(0, compressionTechniques.Length, (i, state2) =>
                {
                    switch (i)
                    {
                    //Uncompressed (only used if no compression technique is smaller)
                    case 0:
                        compressionTechniques[i] = UncompressedBitmapCompressorBitwise.Compress(aBitmap, z);
                        break;

                    //Compress bit channel as an integer array using several techniques, using 8-bit integers
                    case 1:
                        compressionTechniques[i] = ByteArrayCompressorBitwise.Compress(aBitmap, z);
                        break;

                    //Run length compression: save the length of a sequence of bit values instead of saving them seperately
                    case 2:
                        compressionTechniques[i] = RunLengthEncodingCompressorBitwise.Compress(aBitmap, z);
                        break;

                    //Run length compression vertical: run length compression, but scan the pixels horizontally, becouse with some images this yields better results
                    case 3:
                        compressionTechniques[i] = RunLengthEncodingCompressorVerticalBitwise.Compress(aBitmap, z);
                        break;

                        //To add a compression technique, add a new case like the existing ones and increase the length of new byte[??][]
                    }
                });


                //Choose the smallest compression type

                //Initialize
                int smallestID   = 0;               //The ID of the smallest compression type
                int smallestSize = int.MaxValue;    //The size ofthe smallest compression type: int.MaxValue is assigned to make sure that the first compression to be checked will be smaaller than this value

                //Loop trough all saved compression techniques
                for (int i = 0; i < compressionTechniques.Length; i++)
                {
                    //If the current technique is smaller than the smallest technique which has been checked
                    if (compressionTechniques[i].Length < smallestSize)
                    {
                        //Mark this technique as smallest
                        smallestSize = compressionTechniques[i].Length;
                        smallestID   = i;
                    }
                }

                //Merge the number of the compression type of this layer with corresponding bitStream
                BitStreamFIFO tmpStream = new BitStreamFIFO();
                tmpStream.Write(smallestID, 3);    //This 3-bit integer indicates which technique the decompressor should use, and should be before the image data
                byteLayers[z % 8] = BitStreamFIFO.Merge(tmpStream, compressionTechniques[smallestID]);
            });

            //Combine all bitstreams & convert the result to a byte array
            byte[] outputStream = BitStreamFIFO.Merge(byteLayers).ToByteArray();

            //Return the data of all the bit channels combined
            return(outputStream);
        }