public Bitmap WhiteBalance(Bitmap image)
        {
            float percentage = 99.3f;
            var   rHistogram = new Histogram <byte>();
            var   gHistogram = new Histogram <byte>();
            var   bHistogram = new Histogram <byte>();

            var clonedImage = (Bitmap)image.Clone();

            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

            System.Drawing.Imaging.BitmapData bitmapData =
                clonedImage.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, image.PixelFormat);

            IntPtr ptr   = bitmapData.Scan0;
            int    bytes = Math.Abs(bitmapData.Stride) * clonedImage.Height;

            byte[] rgbValues = new byte[bytes];

            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

            for (int i = 0; i < rgbValues.Length - 2; i += 3)
            {
                bHistogram.AddElement(rgbValues[i]);
                gHistogram.AddElement(rgbValues[i + 1]);
                rHistogram.AddElement(rgbValues[i + 2]);
            }

            (var rMin, var rMax) = HistogramStatistics.FindBoundariesOfXPercentage <byte>(rHistogram, percentage);
            (var gMin, var gMax) = HistogramStatistics.FindBoundariesOfXPercentage <byte>(gHistogram, percentage);
            (var bMin, var bMax) = HistogramStatistics.FindBoundariesOfXPercentage <byte>(bHistogram, percentage);

            var rA = 255 / (rMax - rMin);
            var rB = 0 - rA * rMin;
            var gA = 255 / (gMax - gMin);
            var gB = 0 - gA * gMin;
            var bA = (255) / (bMax - bMin);
            var bB = 0 - bA * bMin;

            int val = 0;

            for (int i = 0; i < rgbValues.Length - 2; i += 3)
            {
                val = rA * rgbValues[i + 2] + rB;
                val = val > 255 ? 255 : val < 0 ? 0 : val;
                rgbValues[i + 2] = (byte)val;

                val = gA * rgbValues[i + 1] + gB;
                val = val > 255 ? 255 : val < 0 ? 0 : val;
                rgbValues[i + 1] = (byte)val;

                val          = bA * rgbValues[i] + bB;
                val          = val > 255 ? 255 : val < 0 ? 0 : val;
                rgbValues[i] = (byte)val;
            }

            System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
            clonedImage.UnlockBits(bitmapData);

            return(clonedImage);
        }