SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

OxyPlotで画像のヒストグラム描画

OxyPlotで画像のヒストグラムのグラフを書いてみました。
画像の扱いには、以前取り上げたWriteableBitmapExを使っています。
http://d.hatena.ne.jp/minami_SC/20120927/1348698443

一応全コードは以下の通り。

MainWindow.xaml
<Window x:Class="DrawHistogram.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:oxy="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
        xmlns:series="clr-namespace:OxyPlot.Series;assembly=OxyPlot"
        Title="Histogram" Height="400" Width="600">
    <Grid x:Name="root" Background="Transparent" AllowDrop="True" Drop="root_Drop">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Image Source="{Binding ImageSource}"/>
        <oxy:Plot x:Name="plotHistogram" Grid.Column="1" Model="{Binding Model}"/>
    </Grid>
</Window>
MainWindow.xaml.cs
using OxyPlot;
using OxyPlot.Series;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DrawHistogram
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private string[] _supportExts = { ".bmp", ".jpg", ".jpeg", ".png", ".tif", ".tiff" };
        /// <summary>
        /// 読み込み可能な拡張子リスト
        /// </summary>
        public string[] SupportExts
        {
            get { return _supportExts; }
        }

        public PlotModel Model { get; set; }

        /// <summary>
        /// 表示する画像を取得または設定します
        /// </summary>
        public WriteableBitmap ImageSource
        {
            get { return (WriteableBitmap)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }
        // Using a DependencyProperty as the backing store for ImageSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageSourceProperty =
            DependencyProperty.Register("ImageSource", typeof(WriteableBitmap), typeof(MainWindow), new PropertyMetadata(null));



        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            Model = new PlotModel("Histogram");
            //CalcHistogram();
        }

        private void root_Drop(object sender, DragEventArgs e)
        {
            string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (files == null) return;

            string filename = files[0].ToLower();
            string ext = System.IO.Path.GetExtension(filename);
            if (SupportExts.Any(s => s == ext))
            {
                var img = new BitmapImage(new Uri(filename, UriKind.Absolute));
                ImageSource = BitmapFactory.ConvertToPbgra32Format(img);
                CalcHistogram();
            }
        }

        private void CalcHistogram()
        {
            // ヒストグラムの計算
            int width = ImageSource.PixelWidth;
            int height = ImageSource.PixelHeight;
            var histogramV = new int[256];
            var histogramR = new int[256];
            var histogramG = new int[256];
            var histogramB = new int[256];
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    byte v = ImageSource.GetBrightness(x, y);
                    var col = ImageSource.GetPixel(x, y);
                    histogramV[v]++;
                    histogramR[col.R]++;
                    histogramG[col.G]++;
                    histogramB[col.B]++;
                }
            }

            // グラフの作成
            var seriesV = new StairStepSeries("Brightness")
            {
                Color = OxyColors.Gray,
                VerticalLineStyle = LineStyle.None,
                MarkerType = MarkerType.None
            };
            var seriesR = new StairStepSeries("Red")
            {
                Color = OxyColors.Red,
                VerticalLineStyle = LineStyle.None,
                MarkerType = MarkerType.None
            };
            var seriesG = new StairStepSeries("Green")
            {
                Color = OxyColors.Green,
                VerticalLineStyle = LineStyle.None,
                MarkerType = MarkerType.None
            };
            var seriesB = new StairStepSeries("Blue")
            {
                Color = OxyColors.Blue,
                VerticalLineStyle = LineStyle.None,
                MarkerType = MarkerType.None
            };

            for (int x = 0; x < 256; x++)
            {
                seriesV.Points.Add(new DataPoint(x, histogramV[x]));
                seriesR.Points.Add(new DataPoint(x, histogramR[x]));
                seriesG.Points.Add(new DataPoint(x, histogramG[x]));
                seriesB.Points.Add(new DataPoint(x, histogramB[x]));
            }

            Model.Series.Clear();
            Model.Series.Add(seriesV);
            Model.Series.Add(seriesR);
            Model.Series.Add(seriesG);
            Model.Series.Add(seriesB);

            Model.InvalidatePlot(true);
        }
    }
}