Skip to content

Commit

Permalink
app background
Browse files Browse the repository at this point in the history
  • Loading branch information
Scighost committed Dec 8, 2024
1 parent dccdec3 commit 0c3a1fb
Show file tree
Hide file tree
Showing 14 changed files with 894 additions and 21 deletions.
6 changes: 6 additions & 0 deletions src/Starward/Features/Background/AccentColorChangedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Starward.Features.Background;

internal class AccentColorChangedMessage
{

}
191 changes: 191 additions & 0 deletions src/Starward/Features/Background/AccentColorHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Helpers;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Windows.Storage.Streams;
using Windows.UI;
using WinRT;

namespace Starward.Features.Background;

internal static class AccentColorHelper
{



public unsafe static Color? GetAccentColor(byte[] bgra, int width, int height)
{
if (bgra.Length % 4 == 0)
{
fixed (byte* ptr = bgra)
{
return GetAccentColorInternal(ptr, width, height);
}
}
return null;
}




public unsafe static Color? GetAccentColor(IBuffer buffer, int width, int height)
{
int length = (int)buffer.Length;
if (length > 0 && length % 4 == 0)
{
if (buffer.As<IBufferByteAccess>().Buffer(out nint ptr) == 0)
{
return GetAccentColorInternal((void*)ptr, width, height);
}
}
return null;
}



public unsafe static Color? GetAccentColor(nint bufferPtr, uint capacity, int width, int height)
{
if (capacity > 0 && capacity % 4 == 0)
{
return GetAccentColorInternal((void*)bufferPtr, width, height);
}
return null;
}




private unsafe static Color? GetAccentColorInternal(void* bgra, int width, int height)
{
try
{
uint* p = (uint*)bgra;
long b = 0, g = 0, r = 0;
int[] hueCircle = new int[360];
for (int y = 0; y < height; y += 2)
{
for (int x = 0; x < width; x += 2)
{
Bgra32 pixel = Unsafe.AsRef<Bgra32>(p);
b += pixel.B;
g += pixel.G;
r += pixel.R;
p += 2;
}
p += width - width % 2;
}

int c = (width / 2) * (height / 2);
Unsafe.SkipInit(out Color color);
color.B = (byte)(b / c);
color.G = (byte)(g / c);
color.R = (byte)(r / c);
color.A = 255;
HsvColor hsv = color.ToHsv();

return CommunityToolkit.WinUI.Helpers.ColorHelper.FromHsv(hsv.H, 0.6, hsv.V);
}
catch { }
return null;
}




private static Color ColorMix(Color input, Color blend, double percent)
{
return Color.FromArgb(255,
(byte)(input.R * percent + blend.R * (1 - percent)),
(byte)(input.G * percent + blend.G * (1 - percent)),
(byte)(input.B * percent + blend.B * (1 - percent)));
}



public static void ChangeAppAccentColor(Color? color)
{
if (color is null)
{
return;
}

Color light1 = ColorMix(color.Value, Colors.White, 0.8);
Color light2 = ColorMix(color.Value, Colors.White, 0.6);
Color light3 = ColorMix(color.Value, Colors.White, 0.4);

Application.Current.Resources["SystemAccentColor"] = color;
Application.Current.Resources["SystemAccentColorLight1"] = light1;
Application.Current.Resources["SystemAccentColorLight2"] = light2;
Application.Current.Resources["SystemAccentColorLight3"] = light3;

WeakReferenceMessenger.Default.Send(new AccentColorChangedMessage());
}




[ComImport]
[Guid("905a0fef-bc53-11df-8c49-001e4fc686da")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBufferByteAccess
{
int Buffer([Out] out nint value);
}



[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public unsafe interface IMemoryBufferByteAccess
{
void GetBuffer([Out] out nint buffer, [Out] out uint capacity);
}



[StructLayout(LayoutKind.Explicit, Size = 4)]
private readonly struct Bgra32
{
[FieldOffset(0)] public readonly byte B;
[FieldOffset(1)] public readonly byte G;
[FieldOffset(2)] public readonly byte R;
[FieldOffset(3)] public readonly byte A;
}



[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Bgra32ToHue(in Bgra32 bgra)
{
byte max = Math.Max(Math.Max(bgra.R, bgra.G), bgra.B);
byte min = Math.Min(Math.Min(bgra.R, bgra.G), bgra.B);
float chroma = max - min;
float h;

if (chroma <= 8)
{
// ignore white black gray
h = -1;
}
else if (max == bgra.R)
{
h = (((bgra.G - bgra.B) / chroma) + 6) % 6;
}
else if (max == bgra.G)
{
h = 2 + ((bgra.B - bgra.R) / chroma);
}
else
{
h = 4 + ((bgra.R - bgra.G) / chroma);
}
return (int)(h * 60);
}


}
60 changes: 60 additions & 0 deletions src/Starward/Features/Background/AppBackground.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl x:Class="Starward.Features.Background.AppBackground"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Starward.Features.Background"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sc="using:Starward.Controls"
xmlns:swi="using:Scighost.WinUI.ImageEx"
x:DefaultBindMode="OneWay"
mc:Ignorable="d">

<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppBackgroundImageExStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>

<Grid>

<swi:ImageEx HorizontalAlignment="Center"
VerticalAlignment="Center"
PlaceholderSource="{x:Bind PlacehoderImageSource}"
PlaceholderStretch="UniformToFill"
Source="{x:Bind BackgroundImageSource}"
Stretch="UniformToFill"
Style="{ThemeResource AppBackgroundImageExStyle}" />



<Rectangle Width="400"
Height="400"
HorizontalAlignment="Right"
VerticalAlignment="Top"
IsHitTestVisible="False">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop Offset="0.5" Color="#00000000" />
<GradientStop Offset="1" Color="#60000000" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>


<Rectangle Width="100"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
IsHitTestVisible="False">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="#00000000" />
<GradientStop Offset="1" Color="#60000000" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

</Grid>
</UserControl>
Loading

0 comments on commit 0c3a1fb

Please sign in to comment.