Example #1
0
 public void Add(VQBlock block)
 {
     for (int i = 0; i < Pixels.Length; i++)
     {
         Pixels[i] += block.Pixels[i];
     }
 }
Example #2
0
 public VQCodeBook(int codeBookSize, int blockWidth, int blockHeight)
 {
     Entries = new VQBlock[codeBookSize];
     for (int i = 0; i < Entries.Length; i++)
     {
         Entries[i] = new VQBlock(blockWidth, blockHeight);
     }
 }
Example #3
0
        public double EuclidianDistance(ref VQBlock block)
        {
            double total = 0.0f;

            for (int i = 0; i < Pixels.Length; i++)
            {
                total += System.Numerics.Vector4.DistanceSquared(Pixels[i], block.Pixels[i]);
            }
            return(total);
        }
Example #4
0
        public double EuclidianDistance2x2(ref VQBlock block)
        {
            double total = 0.0;

            total += System.Numerics.Vector4.DistanceSquared(Pixels[0], block.Pixels[0]);
            total += System.Numerics.Vector4.DistanceSquared(Pixels[1], block.Pixels[1]);
            total += System.Numerics.Vector4.DistanceSquared(Pixels[2], block.Pixels[2]);
            total += System.Numerics.Vector4.DistanceSquared(Pixels[3], block.Pixels[3]);
            return(total);
        }
Example #5
0
        /// <summary>
        /// Initializes the code book.
        /// </summary>
        /// <param name="imageBlocks">The blocks of the image.</param>
        /// <param name="codeBookSize">Size of the code book.</param>
        /// <param name="fastInitialization">True for using simple initialization. False uses improved initialization.</param>
        /// <returns></returns>
        private static VQBlock[] InitCodeBook(ref VQBlock[] imageBlocks, int codeBookSize, bool fastInitialization = false)
        {
            if (fastInitialization)
            {
                int       i        = 0;
                VQBlock[] codeBook = new VQBlock[codeBookSize];
                for (i = 0; i < codeBookSize; i++)
                {
                    codeBook[i % codeBookSize] = new VQBlock(imageBlocks[i]);
                }
                for (i = 0; i < imageBlocks.Length; i++)
                {
                    imageBlocks[i].Group = i % codeBookSize;
                }
                return(codeBook);
            }
            else
            {
                int       i           = 0;
                int       imageLength = imageBlocks.Length;
                double    sum         = 0.0;
                double[]  distances   = new double[imageBlocks.Length];
                VQBlock[] codeBook    = new VQBlock[codeBookSize];
                Random    rand        = new Random();

                codeBook[0] = new VQBlock(imageBlocks[rand.Next() % imageBlocks.Length]);
                for (int cluster = 1; cluster < codeBookSize; cluster++)
                {
                    sum = 0;
                    for (i = 0; i < imageLength; i++)
                    {
                        Nearest(imageBlocks[i], codeBook, cluster, ref distances[i]);
                        sum += distances[i];
                    }
                    sum = sum * rand.Next(0x7fff) / (0x7fff - 1.0);
                    for (i = 0; i < imageLength; i++)
                    {
                        if ((sum -= distances[i]) > 0)
                        {
                            continue;
                        }
                        codeBook[cluster] = new VQBlock(imageBlocks[i]);
                        break;
                    }
                }

                double dump = 0.0;
                for (i = 0; i < imageLength; i++)
                {
                    imageBlocks[i].Group = Nearest(imageBlocks[i], codeBook, codeBookSize, ref dump);
                }
                return(codeBook);
            }
        }
Example #6
0
        /// <summary>
        /// Quantizes the bitmap with the given code book.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <param name="codeBook">The code book.</param>
        /// <returns></returns>
        public static byte[] QuantizeImage(Bitmap bitmap, VQCodeBook codeBook)
        {
            VQBlock[] blocks = CreateBlocks(bitmap, codeBook.BlockWidth, codeBook.BlockHeight);
            byte[]    result = new byte[blocks.Length];
            double    dump   = 0.0;

            for (int i = 0; i < blocks.Length; i++)
            {
                VQBlock block = blocks[i];
                result[i] = (byte)Nearest(block, codeBook.Entries, codeBook.Entries.Length, ref dump);
            }
            return(result);
        }
Example #7
0
 public VQBlock(VQBlock block)
 {
     BlockWidth  = block.BlockWidth;
     BlockHeight = block.BlockHeight;
     Group       = block.Group;
     Pixels      = new System.Numerics.Vector4[BlockWidth * BlockHeight];
     for (int i = 0; i < Pixels.Length; i++)
     {
         Pixels[i].X = block.Pixels[i].X;
         Pixels[i].Y = block.Pixels[i].Y;
         Pixels[i].Z = block.Pixels[i].Z;
         Pixels[i].W = block.Pixels[i].W;
     }
 }
Example #8
0
        /// <summary>
        /// Creates the an block array of the given bitmap.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <param name="blockWidth">Width of the blocks.</param>
        /// <param name="blockHeight">Height of the blocks.</param>
        /// <returns></returns>
        public static VQBlock[] CreateBlocks(Bitmap bitmap, int blockWidth = 2, int blockHeight = 2)
        {
            //Read bitmap into buffer
            ConvertBitmapArgb(ref bitmap);
            byte[]     imageBuffer = new byte[bitmap.Width * bitmap.Height * 4];
            BitmapData bitmapData  = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);

            Marshal.Copy(bitmapData.Scan0, imageBuffer, 0, imageBuffer.Length);

            //Convert bitmap to blocks
            int width      = bitmap.Width / blockWidth;
            int height     = bitmap.Height / blockHeight;
            int blockSize  = blockWidth * blockHeight * 4;
            int blockCount = width * height;

            VQBlock[] blocks = new VQBlock[blockCount];

            for (int y = 0; y < bitmap.Height - 1; y += blockHeight)
            {
                for (int x = 0; x < bitmap.Width - 1; x += blockWidth)
                {
                    int blockIndex = (y / blockHeight) * width + (x / blockWidth);
                    blocks[blockIndex] = new VQBlock(blockWidth, blockHeight);

                    for (int k = 0; k < blockHeight; k++)
                    {
                        for (int l = 0; l < blockWidth; l++)
                        {
                            int  imageIndex = ((y + k) * bitmap.Width + (x + l)) * 4;
                            byte b          = imageBuffer[imageIndex];
                            byte g          = imageBuffer[imageIndex + 1];
                            byte r          = imageBuffer[imageIndex + 2];
                            byte a          = imageBuffer[imageIndex + 3];

                            int subVectorIndex = k * blockWidth + l;
                            blocks[blockIndex].Pixels[subVectorIndex].X = b;
                            blocks[blockIndex].Pixels[subVectorIndex].Y = g;
                            blocks[blockIndex].Pixels[subVectorIndex].Z = r;
                            blocks[blockIndex].Pixels[subVectorIndex].W = a;
                        }
                    }
                }
            }
            bitmap.UnlockBits(bitmapData);
            return(blocks);
        }
Example #9
0
        /// <summary>
        /// Finds the nearest matching block of the given code book cluster
        /// </summary>
        /// <param name="block">The block that will be searched for.</param>
        /// <param name="cluster">The code book cluster where the block will be searched in.</param>
        /// <param name="clusterSize">Size of the code book cluster.</param>
        /// <param name="nearestDistance">The nearest distance that was found.</param>
        /// <returns>Nearest group index</returns>
        private static int Nearest(VQBlock block, VQBlock[] cluster, int clusterSize, ref double nearestDistance)
        {
            int    i            = 0;
            int    nearestIndex = 0;
            double distance     = 0;
            double minDistance  = 0;

            for (i = 0; i < clusterSize; i++)
            {
                minDistance  = double.PositiveInfinity;
                nearestIndex = block.Group;
                for (i = 0; i < clusterSize; i++)
                {
                    if (minDistance > (distance = cluster[i].EuclidianDistance(ref block)))
                    {
                        minDistance  = distance;
                        nearestIndex = i;
                    }
                }
            }
            nearestDistance = minDistance;
            return(nearestIndex);
        }
Example #10
0
        /// <summary>
        /// Generates a code book for the given bitmap.
        /// </summary>
        /// <param name="bitmap">The bitmap from which the code book will be generated.</param>
        /// <param name="codeBookSize">Size of the code book.</param>
        /// <param name="blockWidth">Width of the code book blocks.</param>
        /// <param name="blockHeight">Height of the code book blocks.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">The image can't be devided by the given block size!</exception>
        public static VQCodeBook CreateCodebook(Bitmap bitmap, int codeBookSize, int blockWidth = 2, int blockHeight = 2)
        {
            if (bitmap.Width % blockWidth != 0 || bitmap.Height % blockHeight != 0)
            {
                throw new ArgumentException("The image can't be devided by the given block size!");
            }

            //Convert image to blocks
            VQBlock[] imageBlocks = CreateBlocks(bitmap, blockWidth, blockHeight);

            //Create and initialize codebook
            VQBlock[] codeBookBlocks = InitCodeBook(ref imageBlocks, codeBookSize);

            //Create codebook (k-means/Lloyd algorithm)
            int     i             = 0;
            int     j             = 0;
            int     changed       = 0;
            int     nearestIndex  = 0;
            VQBlock imageBlock    = null;
            VQBlock codeBookBlock = null;
            double  dump          = 0.0;
            int     runs          = 0;

            do
            {
                for (i = 0; i < codeBookSize; i++)
                {
                    codeBookBlock       = codeBookBlocks[i];
                    codeBookBlock.Group = 0;
                    codeBookBlock.Zero();
                }
                for (j = 0; j < imageBlocks.Length; j++)
                {
                    imageBlock           = imageBlocks[j];
                    codeBookBlock        = codeBookBlocks[imageBlock.Group];
                    codeBookBlock.Group += 1;
                    codeBookBlock.Add(imageBlock);
                }
                for (i = 0; i < codeBookSize; i++)
                {
                    codeBookBlock = codeBookBlocks[i];
                    codeBookBlock.Div(codeBookBlock.Group);
                }
                changed = 0;
                for (j = 0; j < imageBlocks.Length; j++)
                {
                    imageBlock   = imageBlocks[j];
                    nearestIndex = Nearest(imageBlock, codeBookBlocks, codeBookSize, ref dump);
                    if (nearestIndex != imageBlock.Group)
                    {
                        changed++;
                        imageBlock.Group = nearestIndex;
                    }
                }
                runs++;
            } while (changed > (imageBlocks.Length >> 10));

            for (i = 0; i < codeBookSize; i++)
            {
                codeBookBlock       = codeBookBlocks[i];
                codeBookBlock.Group = i;
            }
            return(new VQCodeBook(codeBookBlocks));
        }