Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
            public AccessibleBitmapBitwise(AccessibleBitmapBytewise aBitmap)
            {
                width      = aBitmap.width;
                height     = aBitmap.height;
                pixelBytes = aBitmap.pixelBytes;

                byte[] tmpBytes = aBitmap.GetRawPixelBytes();
                boolArray = new bool[tmpBytes.Length * 8];
                new BitArray(tmpBytes).CopyTo(boolArray, 0);
            }
Ejemplo n.º 3
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 empty AccessibleBitmapBytewise class with the correct dimensions and color channels
            AccessibleBitmapBytewise outputBitmap = new AccessibleBitmapBytewise(new AccessibleBitmap(width, height, pixelBytes));

            //Initialize
            byte[] inBytes;             //Stores the bytes to feed to the decompressor
            byte[] outBytes = source;   //Stores the bytes which are left by the previous decompressed channel: starts with all the input data

            //Loop trough all color channels
            for (int i = 0; i < pixelBytes; i++)
            {
                //Read compression type from outBytes & copy the rest of them to inBytes so they can be used for the next channel
                int compressionType = outBytes[0];
                inBytes = new byte[outBytes.Length - 1];
                Array.Copy(outBytes, 1, inBytes, 0, inBytes.Length);

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

                //Individual compressed bit channels added together
                case 1:
                    outputBitmap = BitLayerVaryingCompressor.Decompress(inBytes, outputBitmap, out outBytes, i);
                    break;

                //Color channel compressed as integers
                case 2:
                    outputBitmap = ByteArrayCompressorBytewise.Decompress(inBytes, outputBitmap, out outBytes, i);
                    break;

                //Run length compression
                case 3:
                    outputBitmap = RunLengthEncodingCompressorBytewise.Decompress(inBytes, outputBitmap, out outBytes, i);
                    break;

                //Run length encoding vertical
                case 4:
                    outputBitmap = RunLengthEncodingCompressorVerticalBytewise.Decompress(inBytes, outputBitmap, out outBytes, 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");
                }
            }
            return(outputBitmap.GetAccessibleBitmap());
        }
Ejemplo n.º 4
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 byte[] Compress(AccessibleBitmapBytewise source, int byteLayer)
        {
            //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 becouse it will be increased before the first check
            byte       lastPixel    = source.GetPixelByte(0, 0, byteLayer); //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.GetPixelByte(x, y, byteLayer);

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

                        //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.Add(lastPixel);

            //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());
        }
        //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);
        }
        //Compress aBitmap into byte array
        public static byte[] Compress(AccessibleBitmapBytewise source, int byteLayer)
        {
            //Create byte array with a size equal to the amount of pixels in the image
            byte[] output = new byte[source.width * source.height];

            //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 byte of this channel from the current pixel to the correct position in the output array
                    output[y * source.width + x] = source.GetPixelByte(x, y, byteLayer);
                }
            }

            //Return all bytes of this channel
            return(output);
        }
Ejemplo n.º 8
0
        //Compress aBitmap into byte array
        public static byte[] Compress(AccessibleBitmapBytewise source, int byteLayer)
        {
            //Create int array with a size equal to the amount of pixels in the image
            int[] layerByteArray = new int[source.width * source.height];

            //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 byte of this channel from the current pixel to the correct position in the output array
                    layerByteArray[y * source.width + x] = source.GetPixelByte(x, y, byteLayer);
                }
            }

            //Compress the obtained array of integers using different techniques
            byte[] outputArray = VaryingIntArrayCompressor.Compress(layerByteArray).ToByteArray();

            //Return the output array
            return(outputArray);
        }
        //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)
        {
            //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 byte of this channel from the correct position in the input array to the current pixel
                    inBitmap.SetPixelByte(x, y, byteLayer, inBytes[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[inBytes.Length - (inBitmap.width * inBitmap.height)];
            Array.Copy(inBytes, inBitmap.width * inBitmap.height, restBytes, 0, restBytes.Length);

            //Return the modified bitmap so the rest of the channels can be added to complete it
            return(inBitmap);
        }
Ejemplo n.º 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);
        }
Ejemplo n.º 11
0
        //Compress aBitmap into byte array
        public static byte[] Compress(AccessibleBitmap source)
        {
            //Loop trough all layers of bytes, where possible at the same time
            AccessibleBitmapBytewise aBitmap = new AccessibleBitmapBytewise(source);

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

                    //Split color channel in its bit channels and apply compression over them
                    case 1:
                        compressionTechniques[i] = BitLayerVaryingCompressor.Compress(aBitmap, z);
                        break;

                    //Compress color channel as an integer array using several techniques
                    case 2:
                        compressionTechniques[i] = ByteArrayCompressorBytewise.Compress(aBitmap, z);
                        break;

                    //Run length compression: save the length of a sequence of pixels with the same color instead of saving them seperately
                    case 3:
                        compressionTechniques[i] = RunLengthEncodingCompressorBytewise.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 4:
                        compressionTechniques[i] = RunLengthEncodingCompressorVerticalBytewise.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 byte array
                byteLayers[z]    = new byte[compressionTechniques[smallestID].Length + 1];
                byteLayers[z][0] = (byte)smallestID;    //This byte indicates which technique the decompressor should use, and should be before the image data
                Array.Copy(compressionTechniques[smallestID], 0, byteLayers[z], 1, compressionTechniques[smallestID].Length);
            });

            //Combine all byte layers by looping trough all of them and adding them after each other
            List <byte> output = new List <byte>();

            foreach (byte[] b in byteLayers)
            {
                output.AddRange(b);
            }

            //Return the data of all the color channels combined
            return(output.ToArray());
        }