Exemplo n.º 1
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);
        }