diff --git a/XP.Common/Controls/ImageHistogram/ChartRenderer.cs b/XP.Common/Controls/ImageHistogram/ChartRenderer.cs
index bf242a4..b02d5fc 100644
--- a/XP.Common/Controls/ImageHistogram/ChartRenderer.cs
+++ b/XP.Common/Controls/ImageHistogram/ChartRenderer.cs
@@ -13,7 +13,7 @@ namespace XP.Common.Controls.ImageHistogram
internal sealed class ChartRenderer
{
private readonly RadCartesianChart _chart;
- private readonly BarSeries _barSeries;
+ private readonly ScatterAreaSeries _areaSeries;
private readonly LinearAxis _xAxis;
///
@@ -25,12 +25,12 @@ namespace XP.Common.Controls.ImageHistogram
/// 构造函数,接收 RadCartesianChart 实例 | Constructor, receives RadCartesianChart instance
///
/// 图表控件实例 | Chart control instance
- /// 柱状图系列 | Bar series
+ /// 面积图系列 | Area series
/// X 轴 | X axis
- public ChartRenderer(RadCartesianChart chart, BarSeries barSeries, LinearAxis xAxis)
+ public ChartRenderer(RadCartesianChart chart, ScatterAreaSeries areaSeries, LinearAxis xAxis)
{
_chart = chart ?? throw new ArgumentNullException(nameof(chart));
- _barSeries = barSeries ?? throw new ArgumentNullException(nameof(barSeries));
+ _areaSeries = areaSeries ?? throw new ArgumentNullException(nameof(areaSeries));
_xAxis = xAxis ?? throw new ArgumentNullException(nameof(xAxis));
}
@@ -64,6 +64,8 @@ namespace XP.Common.Controls.ImageHistogram
// 设置 X 轴范围 | Set X axis range
_xAxis.Minimum = 0;
_xAxis.Maximum = xAxisMax;
+ // 根据范围自动设置刻度间隔(保持 4-5 个刻度)| Auto set major step based on range (keep 4-5 ticks)
+ _xAxis.MajorStep = xAxisMax <= 255 ? 64 : 16384;
// 构建数据点 | Build data points
var dataPoints = new List();
@@ -103,7 +105,7 @@ namespace XP.Common.Controls.ImageHistogram
}
// 更新图表数据 | Update chart data
- _barSeries.ItemsSource = dataPoints;
+ _areaSeries.ItemsSource = dataPoints;
// 设置 Y 轴范围 | Set Y axis range
UpdateYAxis(displayData, isLogarithmic);
@@ -114,7 +116,7 @@ namespace XP.Common.Controls.ImageHistogram
///
public void Clear()
{
- _barSeries.ItemsSource = null;
+ _areaSeries.ItemsSource = null;
// X 轴范围重置为 0-255 | Reset X axis range to 0-255
_xAxis.Minimum = 0;
@@ -131,9 +133,9 @@ namespace XP.Common.Controls.ImageHistogram
{
get
{
- if (_barSeries.ItemsSource is ICollection collection)
+ if (_areaSeries.ItemsSource is ICollection collection)
return collection.Count;
- if (_barSeries.ItemsSource is IEnumerable enumerable)
+ if (_areaSeries.ItemsSource is IEnumerable enumerable)
return enumerable.Count();
return 0;
}
@@ -173,7 +175,48 @@ namespace XP.Common.Controls.ImageHistogram
if (maxValue == 0)
maxValue = 1;
- SetYAxisRange(0, maxValue, isLogarithmic);
+ // 计算取整的 MajorStep(约 4 个刻度,对齐到 K/M 整数倍)| Calculate rounded MajorStep (~4 ticks, aligned to K/M multiples)
+ if (_chart.VerticalAxis is LinearAxis linearAxis)
+ {
+ long rawStep = maxValue / 4;
+ long step = RoundStepToNice(rawStep);
+ if (step < 1) step = 1;
+ linearAxis.MajorStep = step;
+
+ // 将最大值向上取整到 step 的整数倍 | Round max up to multiple of step
+ long roundedMax = ((maxValue / step) + 1) * step;
+ SetYAxisRange(0, roundedMax, isLogarithmic);
+ }
+ else
+ {
+ SetYAxisRange(0, maxValue, isLogarithmic);
+ }
+ }
+
+ ///
+ /// 将步长取整为"好看"的数值(1, 2, 5 的倍数 × 10^n)| Round step to "nice" value (multiples of 1, 2, 5 × 10^n)
+ /// 例如:123456 → 100000,350000 → 500000,780000 → 1000000
+ ///
+ private static long RoundStepToNice(long rawStep)
+ {
+ if (rawStep <= 0) return 1;
+
+ // 找到数量级 | Find order of magnitude
+ double magnitude = Math.Pow(10, Math.Floor(Math.Log10(rawStep)));
+ double normalized = rawStep / magnitude;
+
+ // 取整到 1, 2, 5 中最近的 | Round to nearest of 1, 2, 5
+ double niceNormalized;
+ if (normalized <= 1.5)
+ niceNormalized = 1;
+ else if (normalized <= 3.5)
+ niceNormalized = 2;
+ else if (normalized <= 7.5)
+ niceNormalized = 5;
+ else
+ niceNormalized = 10;
+
+ return (long)(niceNormalized * magnitude);
}
///
diff --git a/XP.Common/Controls/ImageHistogram/FrequencyLabelConverter.cs b/XP.Common/Controls/ImageHistogram/FrequencyLabelConverter.cs
new file mode 100644
index 0000000..76a76c8
--- /dev/null
+++ b/XP.Common/Controls/ImageHistogram/FrequencyLabelConverter.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace XP.Common.Controls.ImageHistogram
+{
+ ///
+ /// 频次标签转换器:将大数值转为 K/M 缩写格式 | Frequency label converter: converts large values to K/M abbreviation format
+ /// 例如:500000 → "500K",1500000 → "1.5M",800 → "800"
+ ///
+ internal sealed class FrequencyLabelConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null) return "0";
+
+ double num;
+ if (value is double d)
+ num = d;
+ else if (value is decimal dec)
+ num = (double)dec;
+ else if (!double.TryParse(value.ToString(), out num))
+ return value.ToString() ?? "0";
+
+ if (num >= 1_000_000)
+ {
+ double mValue = num / 1_000_000.0;
+ return mValue == Math.Floor(mValue)
+ ? $"{(int)mValue}M"
+ : $"{mValue:0.#}M";
+ }
+
+ if (num >= 1_000)
+ {
+ double kValue = num / 1_000.0;
+ return kValue == Math.Floor(kValue)
+ ? $"{(int)kValue}K"
+ : $"{kValue:0.#}K";
+ }
+
+ return $"{(int)num}";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/XP.Common/Controls/ImageHistogram/ImageHistogramControl.xaml b/XP.Common/Controls/ImageHistogram/ImageHistogramControl.xaml
index 7d1f974..f274cf1 100644
--- a/XP.Common/Controls/ImageHistogram/ImageHistogramControl.xaml
+++ b/XP.Common/Controls/ImageHistogram/ImageHistogramControl.xaml
@@ -3,39 +3,58 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:loc="clr-namespace:XP.Common.Localization.Extensions"
+ xmlns:local="clr-namespace:XP.Common.Controls.ImageHistogram"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="400">
+
+
+
-
+
-
+
+ MajorStep="64"
+ FontSize="9">
+
+
+
+
+
+
-
+
+ FontSize="9">
+
+
+
+
+
+
-
+
-
+
@@ -44,7 +63,7 @@
Text="{loc:Localization Histogram_NoData}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
- FontSize="14"
+ FontSize="12"
Foreground="#9E9E9E"
Visibility="Visible"/>