//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 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 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); }
//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 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); }
//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 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 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); }
//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); }
//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); }
//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); }
//Compress aBitmap into byte array public static byte[] Compress(AccessibleBitmap source) { return(VaryingIntArrayCompressor.Compress(Array.ConvertAll(source.GetRawPixelBytes(), Convert.ToInt32)).ToByteArray()); }