1. 程式人生 > WINDOWS開發 >WPF Adorner 簡易圖片取色器

WPF Adorner 簡易圖片取色器

原文: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;

        }
    }
技術分享圖片