• 【C#/WPF】调节图像的对比度(Contrast)


    关于对比度:
    调节对比度直观感受是,高对比度的图像明暗关系更明显,色彩更鲜艳;低对比度的图像表面像是蒙上一层灰,色彩不鲜艳。

    需求:
    制作一个面板,一个滑动条,拖动滑动条可以修改目标图片的对比度。

    资料参考:


    界面滑动条两端的值是-30~30,默认处于中间位置0。已知目标图像的Bitmap数据。

    1. 修改Bitmap的对比度。
    2. 将修改之后的Bitmap重新赋值给界面Image控件显示。
            /// <summary>
            /// 调节对比度
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Contrast_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                // 滑动条是值是-30~30
                // originalBitmap是目标图像的Bitmap
                int threshold = (int)e.NewValue;
                Bitmap newBitmap = BitmapHelper.Contrast(originalBitmap, threshold);
    
                // 重新给Image控件赋值新图像
                image.Source = SystemUtils.ConvertBitmapToBitmapImage(newBitmap);
            }

    下面调节图像对比度的工具方法:

        
        /// <summary>
        /// 代码来自:https://softwarebydefault.com/2013/04/20/image-contrast/
        /// </summary>
        public static class BitmapHelper
        {
            /// <summary>
            /// 调节图像的对比度
            /// </summary>
            /// <param name="sourceBitmap"></param>
            /// <param name="threshold">阈值,通过该参数控制调节</param>
            /// <returns></returns>
            public static Bitmap Contrast(this Bitmap sourceBitmap, int threshold)
            {
                BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
                                            sourceBitmap.Width, sourceBitmap.Height),
                                            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    
                byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
    
                Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
    
                sourceBitmap.UnlockBits(sourceData);
    
                double contrastLevel = Math.Pow((100.0 + threshold) / 100.0, 2);
    
                double blue = 0;
                double green = 0;
                double red = 0;
    
                for (int k = 0; k + 4 < pixelBuffer.Length; k += 4)
                {
                    blue = ((((pixelBuffer[k] / 255.0) - 0.5) *
                                contrastLevel) + 0.5) * 255.0;
    
                    green = ((((pixelBuffer[k + 1] / 255.0) - 0.5) *
                                contrastLevel) + 0.5) * 255.0;
    
                    red = ((((pixelBuffer[k + 2] / 255.0) - 0.5) *
                                contrastLevel) + 0.5) * 255.0;
    
                    if (blue > 255)
                    { blue = 255; }
                    else if (blue < 0)
                    { blue = 0; }
    
                    if (green > 255)
                    { green = 255; }
                    else if (green < 0)
                    { green = 0; }
    
                    if (red > 255)
                    { red = 255; }
                    else if (red < 0)
                    { red = 0; }
    
                    pixelBuffer[k] = (byte)blue;
                    pixelBuffer[k + 1] = (byte)green;
                    pixelBuffer[k + 2] = (byte)red;
                }
    
                Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
    
                BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
                                            resultBitmap.Width, resultBitmap.Height),
                                            ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    
                Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length);
                resultBitmap.UnlockBits(resultData);
    
                return resultBitmap;
            }
        }

    下面是将Bitmap转换为BitmapImage的工具方法,以供WPF的Image控件使用图像:

        public static class SystemUtils
    {
    /// <summary> /// 转换类型:Bitmap --> BitmapImage /// <summary> /// <returns></returns> public static BitmapImage ConvertBitmapToBitmapImage(Bitmap bitmap) { using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); stream.Position = 0; BitmapImage bi = new BitmapImage(); bi.BeginInit(); // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed." // Force the bitmap to load right now so we can dispose the stream. bi.CacheOption = BitmapCacheOption.OnLoad; bi.StreamSource = stream; bi.EndInit(); bi.Freeze(); return bi; } } }

    测试效果如下:


    另外,关于图像的HSL(色相、饱和度、明度)的调节,可参考在下的另一篇博文:


    参考资料:

    https://softwarebydefault.com/2013/04/20/image-contrast/

  • 相关阅读:
    ASP.NET MVC中多种ActionResult用法总结
    jQuery中异步操作对象Deferred
    jQuery中bind方法和live方法区别解析
    深入理解Javascript中this, prototype, constructor
    SQL及常见的三种类型注释
    SQLServer的两个日期相减(间隔)datediff函数
    SQLServer查询进程与死锁语句
    SqlServer获取当前日期的详细写法
    SQL中 Decode 和 Sign 语法的简单用法
    数据仓库模型之CDM、LDM与PDM的区别
  • 原文地址:https://www.cnblogs.com/guxin/p/csharp-wpf-adjust-image-contrast.html
Copyright © 2020-2023  润新知