圖片灰度處理


一、WPF灰度處理(轉)

文章的內容是來自微軟中文技術論壇的一個帖子,當時是想將一段將圖片灰度處理的代碼轉換為XAML的一個樣式,在這里要謝謝


Xiao Yan Qiang
Sheldon _Xiao、shixin的熱情回答,現在將他們的回答貼出來供大家學習參考.內容如下:

提問: 這個功能如何寫成一個樣式,將一個窗體內所有的Image控件的圖片格式都轉換為Gray8

BitmapImage bitmapImage = new BitmapImage(new Uri("D:\\Face.jpg"));
FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();
newFormatedBitmapSource.BeginInit();
newFormatedBitmapSource.Source = bitmapImage;
newFormatedBitmapSource.DestinationFormat = PixelFormats.Gray8;
newFormatedBitmapSource.EndInit();
img.Source = newFormatedBitmapSource;
this.Content = img;

Xiao Yan Qiang的回答:

public class ImageAttached
{
    // Gray8附加屬性,Gary8圖片樣式的"開關"
public static readonly DependencyProperty Gray8Property =
        DependencyProperty.RegisterAttached("Gray8", typeof(bool), typeof(ImageAttached),
            new FrameworkPropertyMetadata((bool)false,
                new PropertyChangedCallback(OnGray8Changed)));

    public static bool GetGray8(DependencyObject d)
    {
        return (bool)d.GetValue(Gray8Property);
    }

    public static void SetGray8(DependencyObject d, bool value)
    {
        d.SetValue(Gray8Property, value);
    }

    private static void OnGray8Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Image currentImage = d as Image;
        if (currentImage == null)
        {
            return;
        }

        bool isGray8 = (bool)d.GetValue(Gray8Property);

        if (isGray8)
        {
            // 附加BitmapSourceBackup屬性,備份當前BitmapSource,以備恢復用
BitmapSource backupBitmapSource = (currentImage.Source as BitmapSource).CloneCurrentValue();
            d.SetValue(BitmapSourceBackupProperty, backupBitmapSource);

            // 建立Gray8的BitmapSource
FormatConvertedBitmap newFormatedBitmapSource = new FormatConvertedBitmap();
            newFormatedBitmapSource.BeginInit();
            newFormatedBitmapSource.Source = currentImage.Source as BitmapSource;
            newFormatedBitmapSource.DestinationFormat = PixelFormats.Gray8;
            newFormatedBitmapSource.EndInit();

            // 替換ImageSource
currentImage.Source = newFormatedBitmapSource;
        }
        else
        {
            // 圖像恢復操作
object obj = currentImage.GetValue(BitmapSourceBackupProperty);
            if (obj == null)
            {
                return;
            }

            BitmapSource bs = obj as BitmapSource;
            if (bs == null)
            {
                return;
            }

            currentImage.Source = bs;
        }
    }

    // 備份用源圖像的附加屬性,當Gray8變更時,自動附加
public static readonly DependencyProperty BitmapSourceBackupProperty =
        DependencyProperty.RegisterAttached("BitmapSourceBackup", typeof(BitmapSource), typeof(ImageAttached),
            new FrameworkPropertyMetadata(null));

    public static BitmapSource GetBitmapSourceBackup(DependencyObject d)
    {
        return (BitmapSource)d.GetValue(BitmapSourceBackupProperty);
    }

    public static void SetBitmapSourceBackup(DependencyObject d, BitmapSource value)
    {
        d.SetValue(BitmapSourceBackupProperty, value);
    }
}
然后XAML里添加 local:ImageAttached.Gray8="True" 
 
        <Image xmlns:local="clr-namespace:WpfImageGray8Sample" Source="/WpfImageGray8Sample;component/Images/44537119.jpg" local:ImageAttached.Gray8="True" />
 
這樣就可以方便控制Gray8了。
 

 
Sheldon _Xiao

的回答:

 
推薦了一個鏈接: http://www.rikware.com/post/Setting-FormatConvertedBitmap-Source-via-Binding.aspx
 
里面也是用轉換器實現
 
 

shixin的回答:

<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:y="clr-namespace:WpfApplication1"  Title="MainWindow" Height="350" Width="525">
            <Window.Resources>
                <y:GrayImage x:Key="GrayImage" />
            </Window.Resources>
            <Grid>
                <Image Source="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource GrayImage}}" Tag="C:\Test.jpg" />
            </Grid>
        </Window>

xaml部分還可以寫成這樣

<Window.Resources>
            <y:GrayImage x:Key="GrayImage" />
            <Style TargetType="{x:Type Image}">
                <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource GrayImage}}" />
            </Style>
        </Window.Resources>
        <Grid>
            <Image Tag="C:\Test.jpg" />
        </Grid>

Public Class GrayImage
    Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
        Try
            Dim newFormatedBitmapSource As New FormatConvertedBitmap
            newFormatedBitmapSource.BeginInit()
            newFormatedBitmapSource.Source = New BitmapImage(New Uri(value.ToString))
            newFormatedBitmapSource.DestinationFormat = PixelFormats.Gray8
            newFormatedBitmapSource.EndInit()
            Convert = newFormatedBitmapSource
        Catch
            Convert = Nothing
        End Try
    End Function
    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
        ConvertBack = value
    End Function
End Class
二、Windos8和WindowsPhone通過更改像素點顏色更改圖片灰度
private async void Button_Click(object sender, RoutedEventArgs e)
       {
           // 實例化一個 300*300 的 WriteableBitmap,並將其作為 Image 控件的圖片源
           WriteableBitmap writeableBitmap = new WriteableBitmap(300, 300);
           image2.Source = writeableBitmap;

           StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/2.jpg"));
           using (IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read))
           {
               // 將指定的圖片轉換成 BitmapDecoder 對象
               BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);

               // 通過 BitmapTransform 縮放圖片的尺寸
               BitmapTransform transform = new BitmapTransform()
               {
                   ScaledWidth = Convert.ToUInt32(writeableBitmap.PixelWidth),
                   ScaledHeight = Convert.ToUInt32(writeableBitmap.PixelHeight)
               };

               // 獲取圖片的 PixelDataProvider 對象
               PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
                   BitmapPixelFormat.Bgra8,
                   BitmapAlphaMode.Straight,
                   transform,
                   ExifOrientationMode.IgnoreExifOrientation,
                   ColorManagementMode.DoNotColorManage);

               // 獲取圖片的像素數據,由於之前指定的格式是 BitmapPixelFormat.Bgra8,所以每一個像素由 4 個字節組成,分別是 bgra
               byte[] sourcePixels = pixelData.DetachPixelData();
               for (int i = 0; i < sourcePixels.Length; i+=4)
               {                  
                     
                     byte B = sourcePixels[i];
                     byte G = sourcePixels[i + 1];
                     byte R = sourcePixels[i + 2];
                     byte A = sourcePixels[i + 3]; 
                     byte GrayValue = (byte)(R * 0.299 + G * 0.587 + B * 0.114);
                    sourcePixels[i]=GrayValue;
                    sourcePixels[i + 1]=GrayValue;
                    sourcePixels[i + 2]=GrayValue;
                    sourcePixels[i + 3]=0xFF; 
               }
               // 將修改后的像素數據寫入 WriteableBitmap 對象的像素緩沖區(WriteableBitmap 使用的是 BGRA 格式)
               using (Stream stream = writeableBitmap.PixelBuffer.AsStream()) // IBuffer.AsStream() 為來自 System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions 中的擴展方法
               {
                   await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
               }
           }
           // 用像素緩沖區的數據繪制圖片
           writeableBitmap.Invalidate();
       }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM