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();
        }
        /// <summary>
        /// Adds given image in the center of the given plant area and return new image instance
        /// </summary>
        /// <param name="image">Image to plant inside new image</param>
        /// <param name="plantWidthPx">New image width</param>
        /// <param name="plantHeightPx">New image height</param>
        /// <returns></returns>
        public static ImageFrameGrayScale AsPlanted(this ImageFrameGrayScale image, int plantWidthPx, int plantHeightPx)
        {
            var widthCheck = plantWidthPx % 16;

            if (widthCheck != 0)
            {
                throw new ArgumentException("New width is not divisible by 16!");
            }

            var heightCheck = plantHeightPx % 16;

            if (heightCheck != 0)
            {
                throw new ArgumentException("New height is not divisible by 16!");
            }

            if (image.BitsPerPixel != 8)
            {
                throw new NotSupportedException("Only 8 bits per pixel images are supported");
            }

            var newImage = new byte[image.HeaderBytesLength + plantWidthPx * plantHeightPx];

            //copy header from source and ...
            image.Image.CopyBytesTo(0, newImage, 0, image.HeaderBytesLength);

            var leftPx   = plantWidthPx / 2 - image.ImageWidthPx / 2;
            var bottomPx = (plantHeightPx / 2 - image.ImageHeightPx / 2);

            //fill image into plant center
            for (int ir = 0; ir < image.ImageHeightPx; ir++)
            {
                var rowOffSet         = ir * image.ImageWidthPx + image.HeaderBytesLength;
                var newImageRowOffSet = (bottomPx + ir) * plantWidthPx + image.HeaderBytesLength + leftPx;
                for (int ipx = 0; ipx < image.ImageWidthPx; ipx++)
                {
                    var pxIndex    = rowOffSet + ipx;
                    var px         = image.Image[pxIndex];
                    var newPxIndex = newImageRowOffSet + ipx;
                    newImage[newPxIndex] = px;
                }
            }

            var ret = new ImageFrameGrayScale(newImage);

            //.. adjust header with new width and size
            ret.SetSizeInfo((uint)newImage.Length, plantWidthPx, plantHeightPx);

            return(ret);
        }
示例#4
0
        /// <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>
        /// Converts 24 bit color image to gray scale image
        /// </summary>
        /// <param name="image">Color image</param>
        /// <param name="colors">How many gray colors are used in gray image</param>
        /// <returns></returns>
        public static ImageFrameGrayScale AsGrayScale(this ImageFrame image, int colors = 256)
        {
            //--------- write gray scale image header -----------------

            const int headerSize          = ImageFrame.HEADER_BYTES;
            const int colorTableSize      = ImageFrame.HEADER_256_COLOR_TABLE_SIZE;
            var       headerAndColorTable = headerSize + colorTableSize;
            var       newImage            = new byte[image.ImageWidthPx * image.ImageHeightPx + headerAndColorTable];

            //magic bits
            image.Image.CopyBytesTo(0, newImage, 0, 2);

            //file size
            ((uint)(newImage.Length)).AsBytes().CopyBytesTo(newImage, 2);

            //pixel data offset 54 (old header) + 1024 (color table) = 1078
            newImage[10] = 54;
            newImage[11] = 4;

            //header size
            newImage[14] = 40;

            //image width and height
            image.Image.CopyBytesTo(18, newImage, 18, 4);
            image.Image.CopyBytesTo(22, newImage, 22, 4);

            //planes
            image.Image.CopyBytesTo(26, newImage, 26, 2);

            //bits per pixel
            newImage[28] = 8;

            //--------- convert rgb pixels to gray scale

            //linear conversion consts
            const double redLinear   = 0.2126;
            const double greenLinear = 0.7152;
            const double blueLinear  = 0.0722;

            var colorCount = 256 / colors;

            var destIndex = image.HeaderBytesLength + 1024;

            for (int r = 0; r < image.ImageHeightPx; r++)
            {
                var rowStartPos = (r * image.ImageWidthPx * 3) + image.HeaderBytesLength;

                //read each pixel in row
                for (int p = 0; p < image.ImageWidthPx; p++)
                {
                    //pixel is presented as 24 bit (3 bytes)
                    var pixelPos  = rowStartPos + p * 3;
                    var green     = image.Image[pixelPos + 1];
                    var blue      = image.Image[pixelPos];
                    var red       = image.Image[pixelPos + 2];
                    var grayIndex = (int)(red * redLinear + green * greenLinear + blue * blueLinear);
                    var mod       = (grayIndex % colorCount);
                    grayIndex -= mod;
                    var grayIndexByte = (byte)grayIndex;
                    newImage[destIndex++] = grayIndexByte;
                }
            }

            var ret = new ImageFrameGrayScale(newImage);

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