WPF Adorner 簡易圖片取色器
阿新 • • 發佈:2020-05-06
原文:WPF Adorner 簡易圖片取色器
回答MSDN問題所寫。
使用Adorner+附加屬性
圖片類(來自這位博主的部落格)
/// <summary> /// 用於獲取點陣圖畫素的類 /// </summary> public class Imghelper { /// <summary> /// 點陣圖寬度 /// </summary> public int Width { get; protected set; } /// <summary>/// 點陣圖高度 /// </summary> public int Height { get; protected set; } /// <summary> /// 畫素 /// </summary> public Color[][] Pixels { get; protected set; } /// <summary> /// 根據指定的點陣圖生成BitmapPixelHelper類的新例項。 /// </summary>/// <param name="bitmap">指定的點陣圖</param> public Imghelper(BitmapSource bitmap) { FormatConvertedBitmap newBitmap = new FormatConvertedBitmap(bitmap,PixelFormats.Bgra32,BitmapPalettes.WebPaletteTransparent,0); const int bytesPerPixel = 4; Height= newBitmap.PixelHeight; Width = newBitmap.PixelWidth; byte[] data = new byte[Height * Width * bytesPerPixel]; newBitmap.CopyPixels(data,Width * bytesPerPixel,0); Pixels = new Color[Height][]; for (int i = 0; i < Height; ++i) { Pixels[i] = new Color[Width]; for (int j = 0; j < Width; ++j) { Pixels[i][j] = Color.FromArgb( data[(i * Width + j) * bytesPerPixel + 3],data[(i * Width + j) * bytesPerPixel + 2],data[(i * Width + j) * bytesPerPixel + 1],data[(i * Width + j) * bytesPerPixel + 0]); } } } /// <summary> /// 獲取圖片的平均色 /// </summary> public Color GetAverageColor() { int a = 0,r = 0,g = 0,b = 0; for (int i = 0; i < Height; ++i) { for (int j = 0; j < Width; ++j) { a += Pixels[i][j].A; r += Pixels[i][j].R; g += Pixels[i][j].G; b += Pixels[i][j].B; } } a = a / Height / Width; r = r / Height / Width; g = g / Height / Width; b = b / Height / Width; return Color.FromArgb((byte)a,(byte)r,(byte)g,(byte)b); } }
adorner程式碼
public class ShowImagePixelsPopup : Adorner { private TextBlock GetTextBlock; private VisualCollection collection; private UIElement _UIElement; private Border GetBorder; public ShowImagePixelsPopup(UIElement adornedElement) : base(adornedElement) { collection = new VisualCollection(this); GetTextBlock = new TextBlock(); GetTextBlock.Height = 20; GetTextBlock.Width = 120; GetTextBlock.Background = new SolidColorBrush(Colors.Wheat); GetTextBlock.HorizontalAlignment = HorizontalAlignment.Left; GetTextBlock.VerticalAlignment = VerticalAlignment.Top; GetBorder = new Border(); GetBorder.Height = 15; GetBorder.Width = 15; GetBorder.HorizontalAlignment = HorizontalAlignment.Left; GetBorder.VerticalAlignment = VerticalAlignment.Top; collection.Add(GetTextBlock); collection.Add(GetBorder); _UIElement = adornedElement; } protected override int VisualChildrenCount => collection.Count; protected override Visual GetVisualChild(int index) => collection[index]; protected override Size MeasureOverride(Size constraint) => base.MeasureOverride(constraint); public void SetData(Point MousePoint,String Pixels,Color color) { GetTextBlock.Margin = new Thickness(MousePoint.X+7.5,MousePoint.Y-15,0,0); GetBorder.Margin = new Thickness(MousePoint.X-7.5,MousePoint.Y-7.5,0); GetBorder.Background = new SolidColorBrush(color); GetTextBlock.Text = Pixels; } protected override Size ArrangeOverride(Size finalSize) { GetTextBlock.Arrange(new Rect(finalSize)); GetBorder.Arrange(new Rect(finalSize)); return base.ArrangeOverride(finalSize); } }
附加屬性類
public class IsShowImagePixels { public static readonly DependencyProperty IsShowImagePixelsProperty = DependencyProperty.RegisterAttached("IsShowImagePixels",typeof(bool),typeof(IsShowImagePixels),new PropertyMetadata(false,new PropertyChangedCallback(OnIsShowImagePixelsChanged))); public static void SetIsShowImagePixels(DependencyObject d,bool value) => d.SetValue(IsShowImagePixelsProperty,value); public static bool GetIsShowImagePixels(DependencyObject d) => (bool)d.GetValue(IsShowImagePixelsProperty); public static readonly DependencyProperty ShowImagePixelsPointProperty = DependencyProperty.RegisterAttached("ShowImagePixelsPoint",typeof(Point),new PropertyMetadata(new Point(0,0),new PropertyChangedCallback(OnShowImagePixelsPointChanged))); public static void SetIsShowImagePixelsPoint(DependencyObject d,Point value) => d.SetValue(ShowImagePixelsPointProperty,value); public static Point GetShowImagePixelsPoint(DependencyObject d) => (Point)d.GetValue(ShowImagePixelsPointProperty); private static void OnShowImagePixelsPointChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { var c =(Point)e.NewValue; popup.SetData(c,$"X={(((int)c.X ) < 0 ? 0 : (int)c.X )},Y={(((int)c.Y ) < 0 ? 0 : (int)c.Y )}",imghelper.Pixels[((int)c.Y - 1) < 0 ? 0 : (int)c.Y - 1][((int)c.X - 1) < 0 ? 0 : (int)c.X - 1]); } private static AdornerLayer layer; private static Imghelper imghelper; private static ShowImagePixelsPopup popup; private static void OnIsShowImagePixelsChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) { var NewValue = (bool)e.NewValue; UIElement element = d as UIElement; if (!NewValue) { AdornerLayer l = AdornerLayer.GetAdornerLayer(element); var ado = l.GetAdorners(element); for (var o = 0; o < ado.Length; o++) l.Remove(ado[o]); element.MouseMove -= Element_MouseMove; imghelper = null; popup = null; layer = null; element = null; } if (element == null) return; layer = AdornerLayer.GetAdornerLayer(element); popup = new ShowImagePixelsPopup(element); layer.Add(popup); imghelper = new Imghelper((element as Image).Source as BitmapSource); //顯示滑鼠位置 element.MouseMove += Element_MouseMove; } private static void Element_MouseMove(object sender,System.Windows.Input.MouseEventArgs e) { var c = e.GetPosition(sender as FrameworkElement); //此處只是用了滑鼠位置,也可以用ShowImagePixelsPoint直接指定位置 popup.SetData(c,$"X={(((int)c.X - 1) < 0 ? 0 : (int)c.X - 1)},Y={(((int)c.Y - 1) < 0 ? 0 : (int)c.Y - 1)}",imghelper.Pixels[((int)c.Y - 1) < 0 ? 0 : (int)c.Y - 1][((int)c.X - 1) < 0 ? 0 : (int)c.X - 1]); } }
xaml程式碼
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <AdornerDecorator Grid.Row="0"> <Image x:Name="img" /> </AdornerDecorator> <Button Click="Button_Click" Grid.Row="1" Height="40" Content="ShowOrNot"/> </Grid>
cs頁面程式碼
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var b = new BitmapImage(new Uri("timg.jpg",UriKind.RelativeOrAbsolute)); Imghelper imghelper = new Imghelper(b); img.Source = b; img.SetValue(IsShowImagePixels.IsShowImagePixelsProperty,true); Set = true; } private bool Set = false; private void Button_Click(object sender,RoutedEventArgs e) { if (Set) Set = false; else Set = true; img.SetValue(IsShowImagePixels.IsShowImagePixelsProperty,Set); return; } }