public void GlobalSetup() { var sourceFile = Common.GetSourceImagePath(imageIndex); image = ImageFrame.FromFile(sourceFile).AsGrayScale(Colors); LZEncoded = image.AsLZEncodedUsingHashTable(12289); HuffmanEncoded = image.AsHuffmanEncoded(); GZipEncoded = image.AsGZipEncoded(); }
public void GlobalSetup() { var sourceFile = Common.GetSourceImagePath(imageIndex); image = ImageFrame.FromFile(sourceFile).AsCroppedImage(new CropSetup { LeftPx = Crop * 16, RightPx = Crop * 16, TopPx = Crop * 16, BottomPx = Crop * 16 }).AsGrayScale(); LZEncoded = image.AsLZEncodedUsingHashTable(12289); HuffmanEncoded = image.AsHuffmanEncoded(); GZipEncoded = image.AsGZipEncoded(); }
public void AsHuffmanEncodedAndDecodedWithSave(int imageIndex) { var i = imageIndex; var cropSetup = new CropSetup { LeftPx = 27 * 16, RightPx = 29 * 16, TopPx = 1 * 16, BottomPx = 6 * 16 }; var sourceFile = Common.GetSourceImagePath(i); var image = ImageFrame.FromFile(sourceFile).AsCroppedImage(cropSetup).AsGrayScale(); var encodedFilename = Common.GetSaveImagePath(i, "gray-huffman-encoded"); image.AsHuffmanEncoded().Save(encodedFilename); var encoded = new HuffmanImageFrame().Open(encodedFilename); var decodedFilename = Common.GetSaveImagePath(i, "gray-huffman-decoded.bmp"); encoded.AsImageGrayScaleFrame().Save(decodedFilename); var decoded = ImageFrame.FromFile(decodedFilename); Assert.True(image.Image.Compare(decoded.Image)); }
/// <summary> /// Decodes Huffman encoded image back to gray scale image /// </summary> /// <param name="encodedImage"></param> /// <returns></returns> public static ImageFrameGrayScale AsImageGrayScaleFrame(this HuffmanImageFrame encodedImage) { //---------- generate tree from color codes ----------------- var maxNodes = 0; for (int i = 0; i <= encodedImage.MaxCodeBitsLength + 1; i++) { maxNodes = 1 << i; } //simple help table for tree generation var nodeTree = new HuffmanTreeNode <int> [maxNodes - 1]; var rootNode = new HuffmanTreeNode <int>(); nodeTree[0] = rootNode; for (int i = 0; i < encodedImage.ColorCodeCount; i++) { var colorCodeItem = encodedImage.GetColorCodeItemFromHeader(i); var huffmanNode = new HuffmanTreeNode <int>(colorCodeItem.Symbol, colorCodeItem.Code, colorCodeItem.CodeBitsCount); huffmanNode.PopulateBitTable(); //start always from root bit and go to leaf var parentPos = 0; var parent = nodeTree[0]; for (int j = huffmanNode.CodeBitTable.Length - 1; j >= 0; j--) { var childPos = 0; var isRightChild = huffmanNode.CodeBitTable[j]; if (isRightChild) { childPos = ((parentPos + 1) * 2 + 1) - 1; } else { childPos = ((parentPos + 1) * 2) - 1; } if (j == 0) { //leaf node nodeTree[childPos] = huffmanNode; } else if (nodeTree[childPos] == null) { //create internal node nodeTree[childPos] = new HuffmanTreeNode <int>(); } nodeTree[childPos].SetParent(parent, isRightChild); parent.SetChild(nodeTree[childPos]); parent = nodeTree[childPos]; parentPos = childPos; } } var imageHeaderSize = encodedImage.OriginalImageHeaderLength + ImageFrame.HEADER_256_COLOR_TABLE_SIZE; var imageData = new byte[imageHeaderSize + encodedImage.OriginalImageDataLength]; //------------- set header ------------------------ //copy original image non-encoded header to image encodedImage.Data.CopyBytesTo( encodedImage.FixedHeaderLength + encodedImage.ColorCodeHeaderLength, imageData, 0, encodedImage.OriginalImageHeaderLength); //--------------- decode image ----------------------- var node = rootNode; var destIndex = imageHeaderSize; //read encoded stream bit by bit and travel tree using bit value //until leaf node is reached. read original color code from leaf node for (int i = 0; i < encodedImage.CompressedBits; i++) { //read right or left child based bit in stream node = encodedImage.GetBit(i) ? node.RightChild : node.LeftChild; if (node.Leaf) { //set decoded byte to image imageData[destIndex++] = (byte)node.Symbol; //move back to root node node = rootNode; } } var ret = new ImageFrameGrayScale(imageData); //generate color table ret.SetColorTable(); return(ret); }
/// <summary> /// Encodes gray scale image using huffman coding /// </summary> /// <param name="image">Image to encode</param> /// <returns>Huffman image frame</returns> public static HuffmanImageFrame AsHuffmanEncoded(this ImageFrameGrayScale image) { if (image.BitsPerPixel != 8) { throw new NotSupportedException("Only 8 bits per pixel images are supported"); } var colors = (1 << image.BitsPerPixel); var minHeap = new MinHeap <HuffmanTreeNode <int> >(colors); var leafTable = new HuffmanTreeNode <int> [colors]; var leafNodeCount = 0; //iterate through all bytes in image data and calculates color frequency for (int i = image.HeaderBytesLength; i < image.Image.Length; i++) { var colorCode = (int)image.Image[i]; //between 0 - 255 if (leafTable[colorCode] == null) { leafTable[colorCode] = new HuffmanTreeNode <int>(colorCode); leafNodeCount++; } leafTable[colorCode].IncreaseFrequency(); } var leafTableShrink = new HuffmanTreeNode <int> [leafNodeCount]; var shrinkIndex = 0; //add leaf nodes to minheap and shrink table for (int i = 0; i < leafTable.Length; i++) { var leafNode = leafTable[i]; if (leafNode != null) { leafTableShrink[shrinkIndex++] = leafNode; minHeap.Insert(leafNode.Frequency, leafNode); } } var internalNodesCount = 0; //create huffman tree from leaf nodes and internal nodes while (minHeap.HeapSize > 1) { var internalNode = HuffmanTreeNode <int> .InternalNodeCreate(minHeap.DelMin(), minHeap.DelMin()); minHeap.Insert(internalNode.Frequency, internalNode); internalNodesCount++; } //traverse huffman tree from leaf to root and calculate code for node symbol for (int i = 0; i < leafTableShrink.Length; i++) { var node = leafTableShrink[i]; var leafNode = node; leafNode.ResetCode(); while (node != null) { leafNode.SetCodeNextBit(node.IsRightChild ? 1 : 0); node.Parent?.SetChild(node); node = node.Parent; } } var compressedBits = 0; var maxCodeBits = 0; var headerColorItems = new HuffmanImageFrame.HeaderColorItem[leafTableShrink.Length]; for (int i = 0; i < leafTableShrink.Length; i++) { //creates simple array of code bits which is easy iterate in encoding leafTableShrink[i].PopulateBitTable(); compressedBits += leafTableShrink[i].TotalBits; maxCodeBits = leafTableShrink[i].CodeBits > maxCodeBits ? leafTableShrink[i].CodeBits : maxCodeBits; headerColorItems[i] = new HuffmanImageFrame.HeaderColorItem( leafTableShrink[i].Symbol, leafTableShrink[i].CodeBits, leafTableShrink[i].Code); } //------------------ Build return starts -------------------------------------- var originalImageHeader = new byte[ImageFrame.HEADER_BYTES]; image.Image.CopyBytesTo(0, originalImageHeader); var originalImageDataLength = image.Image.Length - image.HeaderBytesLength; var ret = new HuffmanImageFrame(compressedBits, headerColorItems, maxCodeBits, originalImageDataLength, originalImageHeader); var retBitIndex = 7; //read bits from left to right var retByteIndex = ret.ImageDataOffSet; //start begin of image section //encode image bytes per byte using huffman code for (int i = image.HeaderBytesLength; i < image.Image.Length; i++) { //get color encoding info node from leafs table by index var colorCode = (int)image.Image[i]; var leafNode = leafTable[colorCode]; //read bits from bits table from left to right for (int j = leafNode.CodeBitTable.Length - 1; j >= 0; j--) { //write bits to byte from left to right if (retBitIndex == -1) { //switch to next byte and start writing from left of byte (most significant bit) retBitIndex = 7; retByteIndex++; } //dest byte bits are set initally to 0 only change byte value when bit is set to 1 if (leafNode.CodeBitTable[j]) { ret.Data[retByteIndex] = ret.Data[retByteIndex].SetBitToByte(retBitIndex); } retBitIndex--; } } return(ret); }