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