Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions HueCue/HeatMapValueToColorConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;

namespace HueCue;

/// <summary>
/// Converts a heat map value (0.0 to 1.0) to a color brush.
/// 0.0 = Red (bad composition), 1.0 = Green (good composition)
/// </summary>
public class HeatMapValueToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double heatValue)
{
// Clamp value between 0.0 and 1.0
heatValue = Math.Max(0.0, Math.Min(1.0, heatValue));

// Linear interpolation from red (0.0) to green (1.0)
byte red = (byte)(255 * (1 - heatValue));
byte green = (byte)(255 * heatValue);
byte blue = 0;

return new SolidColorBrush(Color.FromRgb(red, green, blue));
}

// Default to transparent if value is not a double
return new SolidColorBrush(Colors.Transparent);
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
136 changes: 107 additions & 29 deletions HueCue/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<local:HistogramOverlayToBooleanConverter x:Key="HistogramOverlayToBooleanConverter" />
<local:GuideOverlayToBooleanConverter x:Key="GuideOverlayToBooleanConverter" />
<local:ThirdsConverter x:Key="ThirdsConverter" />
<local:HeatMapValueToColorConverter x:Key="HeatMapValueToColorConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
Expand Down Expand Up @@ -149,7 +150,8 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="{Binding ActualWidth, ElementName=VideoImage}"
Height="{Binding ActualHeight, ElementName=VideoImage}">
Height="{Binding ActualHeight, ElementName=VideoImage}"
Opacity="0.5">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Visibility" Value="Collapsed"/>
Expand All @@ -164,47 +166,123 @@
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<!-- Upper left (medium green) -->
<Rectangle Grid.Row="0" Grid.Column="0"
Fill="#00B400"
Opacity="0.3"/>
<!-- Row 0 -->
<Rectangle Grid.Row="0" Grid.Column="0" Fill="{Binding HeatMapMatrix[0][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="1" Fill="{Binding HeatMapMatrix[0][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="2" Fill="{Binding HeatMapMatrix[0][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="3" Fill="{Binding HeatMapMatrix[0][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="4" Fill="{Binding HeatMapMatrix[0][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="5" Fill="{Binding HeatMapMatrix[0][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="6" Fill="{Binding HeatMapMatrix[0][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="7" Fill="{Binding HeatMapMatrix[0][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="0" Grid.Column="8" Fill="{Binding HeatMapMatrix[0][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Row 1 -->
<Rectangle Grid.Row="1" Grid.Column="0" Fill="{Binding HeatMapMatrix[1][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="1" Fill="{Binding HeatMapMatrix[1][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="2" Fill="{Binding HeatMapMatrix[1][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="3" Fill="{Binding HeatMapMatrix[1][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="4" Fill="{Binding HeatMapMatrix[1][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="5" Fill="{Binding HeatMapMatrix[1][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="6" Fill="{Binding HeatMapMatrix[1][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="7" Fill="{Binding HeatMapMatrix[1][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="1" Grid.Column="8" Fill="{Binding HeatMapMatrix[1][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Row 2 -->
<Rectangle Grid.Row="2" Grid.Column="0" Fill="{Binding HeatMapMatrix[2][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="1" Fill="{Binding HeatMapMatrix[2][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="2" Fill="{Binding HeatMapMatrix[2][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="3" Fill="{Binding HeatMapMatrix[2][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="4" Fill="{Binding HeatMapMatrix[2][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="5" Fill="{Binding HeatMapMatrix[2][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="6" Fill="{Binding HeatMapMatrix[2][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="7" Fill="{Binding HeatMapMatrix[2][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="2" Grid.Column="8" Fill="{Binding HeatMapMatrix[2][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Upper center (bright green) -->
<Rectangle Grid.Row="0" Grid.Column="1"
Fill="#00FF00"
Opacity="0.3"/>
<!-- Row 3 -->
<Rectangle Grid.Row="3" Grid.Column="0" Fill="{Binding HeatMapMatrix[3][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="1" Fill="{Binding HeatMapMatrix[3][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="2" Fill="{Binding HeatMapMatrix[3][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="3" Fill="{Binding HeatMapMatrix[3][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="4" Fill="{Binding HeatMapMatrix[3][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="5" Fill="{Binding HeatMapMatrix[3][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="6" Fill="{Binding HeatMapMatrix[3][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="7" Fill="{Binding HeatMapMatrix[3][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="3" Grid.Column="8" Fill="{Binding HeatMapMatrix[3][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Upper right (medium green) -->
<Rectangle Grid.Row="0" Grid.Column="2"
Fill="#00B400"
Opacity="0.3"/>
<!-- Row 4 -->
<Rectangle Grid.Row="4" Grid.Column="0" Fill="{Binding HeatMapMatrix[4][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="1" Fill="{Binding HeatMapMatrix[4][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="2" Fill="{Binding HeatMapMatrix[4][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="3" Fill="{Binding HeatMapMatrix[4][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="4" Fill="{Binding HeatMapMatrix[4][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="5" Fill="{Binding HeatMapMatrix[4][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="6" Fill="{Binding HeatMapMatrix[4][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="7" Fill="{Binding HeatMapMatrix[4][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="4" Grid.Column="8" Fill="{Binding HeatMapMatrix[4][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Middle left (yellow) -->
<Rectangle Grid.Row="1" Grid.Column="0"
Fill="#C8C800"
Opacity="0.3"/>
<!-- Row 5 -->
<Rectangle Grid.Row="5" Grid.Column="0" Fill="{Binding HeatMapMatrix[5][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="1" Fill="{Binding HeatMapMatrix[5][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="2" Fill="{Binding HeatMapMatrix[5][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="3" Fill="{Binding HeatMapMatrix[5][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="4" Fill="{Binding HeatMapMatrix[5][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="5" Fill="{Binding HeatMapMatrix[5][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="6" Fill="{Binding HeatMapMatrix[5][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="7" Fill="{Binding HeatMapMatrix[5][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="5" Grid.Column="8" Fill="{Binding HeatMapMatrix[5][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Middle center (light green) -->
<Rectangle Grid.Row="1" Grid.Column="1"
Fill="#007800"
Opacity="0.3"/>
<!-- Row 6 -->
<Rectangle Grid.Row="6" Grid.Column="0" Fill="{Binding HeatMapMatrix[6][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="1" Fill="{Binding HeatMapMatrix[6][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="2" Fill="{Binding HeatMapMatrix[6][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="3" Fill="{Binding HeatMapMatrix[6][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="4" Fill="{Binding HeatMapMatrix[6][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="5" Fill="{Binding HeatMapMatrix[6][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="6" Fill="{Binding HeatMapMatrix[6][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="7" Fill="{Binding HeatMapMatrix[6][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="6" Grid.Column="8" Fill="{Binding HeatMapMatrix[6][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Middle right (yellow) -->
<Rectangle Grid.Row="1" Grid.Column="2"
Fill="#C8C800"
Opacity="0.3"/>
<!-- Row 7 -->
<Rectangle Grid.Row="7" Grid.Column="0" Fill="{Binding HeatMapMatrix[7][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="1" Fill="{Binding HeatMapMatrix[7][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="2" Fill="{Binding HeatMapMatrix[7][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="3" Fill="{Binding HeatMapMatrix[7][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="4" Fill="{Binding HeatMapMatrix[7][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="5" Fill="{Binding HeatMapMatrix[7][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="6" Fill="{Binding HeatMapMatrix[7][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="7" Fill="{Binding HeatMapMatrix[7][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="7" Grid.Column="8" Fill="{Binding HeatMapMatrix[7][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>

<!-- Bottom (red) - spans all columns -->
<Rectangle Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
Fill="#FF0000"
Opacity="0.3"/>
<!-- Row 8 -->
<Rectangle Grid.Row="8" Grid.Column="0" Fill="{Binding HeatMapMatrix[8][0], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="1" Fill="{Binding HeatMapMatrix[8][1], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="2" Fill="{Binding HeatMapMatrix[8][2], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="3" Fill="{Binding HeatMapMatrix[8][3], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="4" Fill="{Binding HeatMapMatrix[8][4], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="5" Fill="{Binding HeatMapMatrix[8][5], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="6" Fill="{Binding HeatMapMatrix[8][6], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="7" Fill="{Binding HeatMapMatrix[8][7], Converter={StaticResource HeatMapValueToColorConverter}}"/>
<Rectangle Grid.Row="8" Grid.Column="8" Fill="{Binding HeatMapMatrix[8][8], Converter={StaticResource HeatMapValueToColorConverter}}"/>
</Grid>

<!-- Histogram overlay -->
Expand Down
18 changes: 18 additions & 0 deletions HueCue/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,24 @@ partial void OnFaceDetectionEnabledChanged(bool oldValue, bool newValue)
[ObservableProperty]
private bool _topMost;

/// <summary>
/// Heat map matrix values representing composition quality.
/// Values range from 0.0 (bad/red) to 1.0 (good/green).
/// Matrix is organized as [row][column] with 9x9 grid.
/// </summary>
public double[][] HeatMapMatrix { get; } = new[]
{
new[] { 0.1, 0.5, 0.1, 1.0, 1.0, 1.0, 1.0, 0.5, 0.1 },
new[] { 0.2, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0, 0.7, 0.2 },
new[] { 0.2, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0, 0.7, 0.2 },
new[] { 0.1, 0.6, 1.0, 1.0, 1.0, 1.0, 1.0, 0.6, 0.1 },
new[] { 0.1, 0.5, 0.8, 0.8, 0.8, 0.8, 0.8, 0.5, 0.1 },
new[] { 0.1, 0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.1 },
new[] { 0.0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.1, 0.0 },
new[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
};

public MainWindowViewModel()
{
_playbackTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(33) }; // ~30 FPS
Expand Down
Loading