WPF图像灰度拉伸

图像灰度拉神,主要是将图像的灰度拉伸至全灰度区间,计算公式如下:

 

  •  xaml代码
<Window x:Class="ImageProcess_GrayStretch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ImageProcess_GrayStretch"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Image Name="img" Stretch="Uniform"/>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Content="Load Bitmap" Margin="5" Click="Load_Click"/>
            <Button Content="Gray Stretch" Margin="5" Click="GrayStretch_Click"/>
        </StackPanel>
    </Grid>
</Window>
  • 后台代码
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ImageProcess_GrayStretch
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private byte GetMaxValue(byte[] rgbValues)
        {
            byte maxi = rgbValues[0];
            for (int i = 0; i < rgbValues.Length; i++)
            {
                if (maxi < rgbValues[i])
                {
                    maxi = rgbValues[i];
                }
            }
            return maxi;
        }

        private byte GetMinValue(byte[] rgbValues)
        {
            byte mini = rgbValues[0];
            for (int i = 0; i < rgbValues.Length; i++)
            {
                if (mini > rgbValues[i])
                {
                    mini = rgbValues[i];
                }
            }
            return mini;
        }

        private void BitmapGrayStretch(Bitmap curBitmap, int width, int height)
        {
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, width, height);
            BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = width * height * 4;
            byte[] rgbValues = new byte[bytes];
            Marshal.Copy(ptr, rgbValues, 0, bytes);
            byte[] matGray = new byte[width * height];
            for (int i = 0; i < rgbValues.Length; i = i + 4)
            {
                byte alpha = rgbValues[i + 3];
                byte red = rgbValues[i + 2];
                byte green = rgbValues[i + 1];
                byte blue = rgbValues[i];
                byte gray = (byte)(red * 0.299 + green * 0.587 + blue * 0.114);
                matGray[i / 4] = gray;
            }
            byte maxGray = GetMaxValue(matGray);
            byte minGray = GetMinValue(matGray);
            double f = 0;
            if (maxGray != minGray)
            {
                f = 255.0 / (maxGray - minGray);
            }
            for (int i = 0; i < rgbValues.Length; i = i + 4)
            {
                rgbValues[i] = (byte)(f * (matGray[i / 4] - minGray));
                rgbValues[i + 1] = (byte)(f * (matGray[i / 4] - minGray));
                rgbValues[i + 2] = (byte)(f * (matGray[i / 4] - minGray));
            }
            Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
        }

        private Bitmap ImageSourceToBitmap(ImageSource imageSource)
        {
            BitmapSource bitmapSource = (BitmapSource)imageSource;
            Bitmap bmp = new Bitmap(bitmapSource.PixelWidth, bitmapSource.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            BitmapData data = bmp.LockBits(
                new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            bitmapSource.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
            bmp.UnlockBits(data);
            return bmp;
        }

        private BitmapImage BitmapToBitmapImage(Bitmap bitmap)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                bitmap.Save(stream, ImageFormat.Png);
                stream.Position = 0;
                BitmapImage result = new BitmapImage();
                result.BeginInit();
                result.CacheOption = BitmapCacheOption.OnLoad;
                result.StreamSource = stream;
                result.EndInit();
                result.Freeze();
                return result;
            }
        }

        private void Load_Click(object sender, RoutedEventArgs e)
        {
            img.Source = new BitmapImage(new Uri(@"D:\程序项目目录\ImgList\World.jpg", UriKind.RelativeOrAbsolute));
        }

        private void GrayStretch_Click(object sender, RoutedEventArgs e)
        {
            Bitmap bitmap = ImageSourceToBitmap(img.Source);
            BitmapGrayStretch(bitmap, bitmap.Width, bitmap.Height);
            img.Source = BitmapToBitmapImage(bitmap);
        }
    }
}

技术要领: 采用内存方式一次性加载整个图片,效率高,如果用循环的方式,采用GetPixel方式来获取像素RGB值,效率极低,这幅图片的size为2048*1025,循环方式特别慢。

猜你喜欢

转载自blog.csdn.net/u012366767/article/details/81480695