void LoopTree(bool[] currentTree, int index)
        {
            int[] node = treeints[index];
            if (node[1] == -1)
            {
                if (currentTree.Length == 0)
                {
                    currentTree = new bool[] { false };
                }

                //Console.Write("0 " + sortednumbers[node[2]] + " ");
                outputStream.Write(false);
                outputStream.Write(sortednumbers[node[2]], minBits);

                numberVals[node[2]] = currentTree.ToArray();
            }
            else
            {
                //Console.Write("1");
                outputStream.Write(true);

                bool[] passTree = new bool[currentTree.Length + 1];
                if (currentTree.Length > 0)
                {
                    Array.Copy(currentTree, passTree, currentTree.Length);
                }

                passTree[passTree.Length - 1] = true;
                LoopTree(passTree, node[2]);
                passTree[passTree.Length - 1] = false;
                LoopTree(passTree, node[1]);
            }
        }
Exemple #2
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]));
        }
        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();
        }
Exemple #4
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());
        }
Exemple #5
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);
        }
        //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);
        }
        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);
        }
Exemple #8
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();
        }
Exemple #9
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);
        }
Exemple #10
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);
        }