【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,循环方式特别慢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF中,当一个Button控件不可用时,可以通过改变按钮上的图像灰度图来达到变灰的效果。 一种实现方式是使用Button的样式和触发器来实现。首先,我们需要将按钮的样式定义在XAML中,在其中设置按钮的模板,并在其中添加一个Image元素用于显示图像。在按钮的样式中,为按钮的IsEnabled属性添加一个触发器,当该属性值为False时,触发器会将图像转为灰度。 以下是一个简单的实现示例: ```xml <Button Content="按钮" IsEnabled="False"> <Button.Style> <Style TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Image Source="图片路径"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Effect"> <Setter.Value> <GrayscaleEffect/> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> </Button.Style> </Button> ``` 在上述示例中,首先定义了一个Button,并设置其Content属性为"按钮",IsEnabled属性为False。然后,定义了一个样式,并将按钮的模板设置为一个包含Image的网格布局。 接下来,在该样式的触发器中,当按钮的IsEnabled属性为False时,设置按钮的Effect属性为GrayscaleEffect,即灰度效果。这里GrayscaleEffect是一个自定义的灰度特效。 以上就是一种在WPF中实现按钮不可用时图像灰度图的方法。通过定义控件样式和触发器,我们可以根据按钮的可用性状态来改变按钮上的图像效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值