- Add album text in lyrics render
- Improve song info update and draw algo
- Upgrade to .NET 10
This commit is contained in:
Zhe Fang
2025-11-12 19:15:19 -05:00
parent 008c80c886
commit 4926fe55a3
198 changed files with 367 additions and 1211 deletions

View File

@@ -20,12 +20,12 @@ namespace ColorThiefDotNet
public List<QuantizedColor> GeneratePalette()
{
if(palette == null)
if (palette == null)
{
palette = (from vBox in vboxes
let rgb = vBox.Avg(false)
let color = FromRgb(rgb[0], rgb[1], rgb[2])
select new QuantizedColor(color, vBox.Count(false))).ToList();
let rgb = vBox.Avg(false)
let color = FromRgb(rgb[0], rgb[1], rgb[2])
select new QuantizedColor(color, vBox.Count(false))).ToList();
}
return palette;
@@ -38,7 +38,7 @@ namespace ColorThiefDotNet
public int[] Map(int[] color)
{
foreach(var vbox in vboxes.Where(vbox => vbox.Contains(color)))
foreach (var vbox in vboxes.Where(vbox => vbox.Contains(color)))
{
return vbox.Avg(false);
}
@@ -50,13 +50,13 @@ namespace ColorThiefDotNet
var d1 = double.MaxValue;
int[] pColor = null;
foreach(var t in vboxes)
foreach (var t in vboxes)
{
var vbColor = t.Avg(false);
var d2 = Math.Sqrt(Math.Pow(color[0] - vbColor[0], 2)
+ Math.Pow(color[1] - vbColor[1], 2)
+ Math.Pow(color[2] - vbColor[2], 2));
if(d2 < d1)
if (d2 < d1)
{
d1 = d2;
pColor = vbColor;
@@ -71,20 +71,20 @@ namespace ColorThiefDotNet
double maxValue = 0;
var highestPopulation = vboxes.Select(p => p.Count(false)).Max();
foreach(var swatch in vboxes)
foreach (var swatch in vboxes)
{
var avg = swatch.Avg(false);
var hsl = FromRgb(avg[0], avg[1], avg[2]).ToHsl();
var sat = hsl.S;
var luma = hsl.L;
if(sat >= minSaturation && sat <= maxSaturation &&
if (sat >= minSaturation && sat <= maxSaturation &&
luma >= minLuma && luma <= maxLuma)
{
var thisValue = Mmcq.CreateComparisonValue(sat, targetSaturation, luma, targetLuma,
swatch.Count(false), highestPopulation);
if(max == null || thisValue > maxValue)
if (max == null || thisValue > maxValue)
{
max = swatch;
maxValue = thisValue;

View File

@@ -43,25 +43,25 @@ namespace ColorThiefDotNet
double h1;
// ReSharper disable CompareOfFloatsByEqualityOperator
if(chroma == 0)
if (chroma == 0)
{
h1 = 0;
}
else if(max == r)
else if (max == r)
{
h1 = (g - b) / chroma % 6;
}
else if(max == g)
else if (max == g)
{
h1 = 2 + (b - r) / chroma;
}
else //if (max == b)
{
h1 = 4 + (r - g)/chroma;
h1 = 4 + (r - g) / chroma;
}
var lightness = 0.5 * (max - min);
var saturation = chroma == 0 ? 0 : chroma / (1 - Math.Abs(2*lightness - 1));
var saturation = chroma == 0 ? 0 : chroma / (1 - Math.Abs(2 * lightness - 1));
HslColor ret;
ret.H = 60 * h1;
ret.S = saturation;
@@ -83,7 +83,7 @@ namespace ColorThiefDotNet
public override string ToString()
{
if(A == 255)
if (A == 255)
{
return ToHexString();
}

View File

@@ -53,7 +53,7 @@ namespace ColorThiefDotNet
{
var pixelArray = await GetPixelsFast(sourceImage, quality, ignoreWhite);
var cmap = GetColorMap(pixelArray, colorCount);
if(cmap != null)
if (cmap != null)
{
var colors = cmap.GeneratePalette();
return colors;
@@ -70,13 +70,13 @@ namespace ColorThiefDotNet
private async Task<byte[][]> GetPixelsFast(BitmapDecoder sourceImage, int quality, bool ignoreWhite)
{
if(quality < 1)
if (quality < 1)
{
quality = DefaultQuality;
}
var pixels = await GetIntFromPixel(sourceImage);
var pixelCount = sourceImage.PixelWidth*sourceImage.PixelHeight;
var pixelCount = sourceImage.PixelWidth * sourceImage.PixelHeight;
return ConvertPixels(pixels, Convert.ToInt32(pixelCount), quality, ignoreWhite);
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<RootNamespace>ColorThief.WinUI3</RootNamespace>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>

View File

@@ -31,10 +31,10 @@ namespace ColorThiefDotNet
private byte[][] ConvertPixels(byte[] pixels, int pixelCount, int quality, bool ignoreWhite)
{
var expectedDataLength = pixelCount * ColorDepth;
if(expectedDataLength != pixels.Length)
if (expectedDataLength != pixels.Length)
{
throw new ArgumentException("(expectedDataLength = "
+ expectedDataLength + ") != (pixels.length = "
@@ -52,7 +52,7 @@ namespace ColorThiefDotNet
var numUsedPixels = 0;
var pixelArray = new byte[numRegardedPixels][];
for(var i = 0; i < pixelCount; i += quality)
for (var i = 0; i < pixelCount; i += quality)
{
var offset = i * ColorDepth;
var b = pixels[offset];
@@ -61,9 +61,9 @@ namespace ColorThiefDotNet
var a = pixels[offset + 3];
// If pixel is mostly opaque and not white
if(a >= 125 && !(ignoreWhite && r > 250 && g > 250 && b > 250))
if (a >= 125 && !(ignoreWhite && r > 250 && g > 250 && b > 250))
{
pixelArray[numUsedPixels] = new[] {r, g, b};
pixelArray[numUsedPixels] = new[] { r, g, b };
numUsedPixels++;
}
}

View File

@@ -32,7 +32,7 @@ namespace ColorThiefDotNet
{
var histo = new int[Histosize];
foreach(var pixel in pixels)
foreach (var pixel in pixels)
{
var rval = pixel[0] >> Rshift;
var gval = pixel[1] >> Rshift;
@@ -51,36 +51,36 @@ namespace ColorThiefDotNet
// find min/max
var numPixels = pixels.Count;
for(var i = 0; i < numPixels; i++)
for (var i = 0; i < numPixels; i++)
{
var pixel = pixels[i];
var rval = pixel[0] >> Rshift;
var gval = pixel[1] >> Rshift;
var bval = pixel[2] >> Rshift;
if(rval < rmin)
if (rval < rmin)
{
rmin = rval;
}
else if(rval > rmax)
else if (rval > rmax)
{
rmax = rval;
}
if(gval < gmin)
if (gval < gmin)
{
gmin = gval;
}
else if(gval > gmax)
else if (gval > gmax)
{
gmax = gval;
}
if(bval < bmin)
if (bval < bmin)
{
bmin = bval;
}
else if(bval > bmax)
else if (bval > bmax)
{
bmax = bval;
}
@@ -94,7 +94,7 @@ namespace ColorThiefDotNet
int vboxDim1;
int vboxDim2;
switch(color)
switch (color)
{
case 'r':
vboxDim1 = vbox.R1;
@@ -110,9 +110,9 @@ namespace ColorThiefDotNet
break;
}
for(var i = vboxDim1; i <= vboxDim2; i++)
for (var i = vboxDim1; i <= vboxDim2; i++)
{
if(partialsum[i] > total / 2)
if (partialsum[i] > total / 2)
{
var vbox1 = vbox.Clone();
var vbox2 = vbox.Clone();
@@ -125,18 +125,18 @@ namespace ColorThiefDotNet
: Math.Max(vboxDim1, Math.Abs(Convert.ToInt32(i - 1 - left / 2.0)));
// avoid 0-count boxes
while(d2 < 0 || partialsum[d2] <= 0)
while (d2 < 0 || partialsum[d2] <= 0)
{
d2++;
}
var count2 = lookaheadsum[d2];
while(count2 == 0 && d2 > 0 && partialsum[d2 - 1] > 0)
while (count2 == 0 && d2 > 0 && partialsum[d2 - 1] > 0)
{
count2 = lookaheadsum[--d2];
}
// set dimensions
switch(color)
switch (color)
{
case 'r':
vbox1.R2 = d2;
@@ -152,7 +152,7 @@ namespace ColorThiefDotNet
break;
}
return new[] {vbox1, vbox2};
return new[] { vbox1, vbox2 };
}
}
@@ -161,13 +161,13 @@ namespace ColorThiefDotNet
private static VBox[] MedianCutApply(IList<int> histo, VBox vbox)
{
if(vbox.Count(false) == 0)
if (vbox.Count(false) == 0)
{
return null;
}
if(vbox.Count(false) == 1)
if (vbox.Count(false) == 1)
{
return new[] {vbox.Clone(), null};
return new[] { vbox.Clone(), null };
}
// only one pixel, no split
@@ -181,28 +181,28 @@ namespace ColorThiefDotNet
var total = 0;
var partialsum = new int[VboxLength];
// -1 = not set / 0 = 0
for(var l = 0; l < partialsum.Length; l++)
for (var l = 0; l < partialsum.Length; l++)
{
partialsum[l] = -1;
}
// -1 = not set / 0 = 0
var lookaheadsum = new int[VboxLength];
for(var l = 0; l < lookaheadsum.Length; l++)
for (var l = 0; l < lookaheadsum.Length; l++)
{
lookaheadsum[l] = -1;
}
int i, j, k, sum, index;
if(maxw == rw)
if (maxw == rw)
{
for(i = vbox.R1; i <= vbox.R2; i++)
for (i = vbox.R1; i <= vbox.R2; i++)
{
sum = 0;
for(j = vbox.G1; j <= vbox.G2; j++)
for (j = vbox.G1; j <= vbox.G2; j++)
{
for(k = vbox.B1; k <= vbox.B2; k++)
for (k = vbox.B1; k <= vbox.B2; k++)
{
index = GetColorIndex(i, j, k);
sum += histo[index];
@@ -212,14 +212,14 @@ namespace ColorThiefDotNet
partialsum[i] = total;
}
}
else if(maxw == gw)
else if (maxw == gw)
{
for(i = vbox.G1; i <= vbox.G2; i++)
for (i = vbox.G1; i <= vbox.G2; i++)
{
sum = 0;
for(j = vbox.R1; j <= vbox.R2; j++)
for (j = vbox.R1; j <= vbox.R2; j++)
{
for(k = vbox.B1; k <= vbox.B2; k++)
for (k = vbox.B1; k <= vbox.B2; k++)
{
index = GetColorIndex(j, i, k);
sum += histo[index];
@@ -231,12 +231,12 @@ namespace ColorThiefDotNet
}
else /* maxw == bw */
{
for(i = vbox.B1; i <= vbox.B2; i++)
for (i = vbox.B1; i <= vbox.B2; i++)
{
sum = 0;
for(j = vbox.R1; j <= vbox.R2; j++)
for (j = vbox.R1; j <= vbox.R2; j++)
{
for(k = vbox.G1; k <= vbox.G2; k++)
for (k = vbox.G1; k <= vbox.G2; k++)
{
index = GetColorIndex(j, k, i);
sum += histo[index];
@@ -247,9 +247,9 @@ namespace ColorThiefDotNet
}
}
for(i = 0; i < VboxLength; i++)
for (i = 0; i < VboxLength; i++)
{
if(partialsum[i] != -1)
if (partialsum[i] != -1)
{
lookaheadsum[i] = total - partialsum[i];
}
@@ -273,10 +273,10 @@ namespace ColorThiefDotNet
var ncolors = 1;
var niters = 0;
while(niters < MaxIterations)
while (niters < MaxIterations)
{
var vbox = lh[lh.Count - 1];
if(vbox.Count(false) == 0)
if (vbox.Count(false) == 0)
{
lh.Sort(comparator);
niters++;
@@ -290,25 +290,25 @@ namespace ColorThiefDotNet
var vbox1 = vboxes[0];
var vbox2 = vboxes[1];
if(vbox1 == null)
if (vbox1 == null)
{
throw new Exception(
"vbox1 not defined; shouldn't happen!");
}
lh.Add(vbox1);
if(vbox2 != null)
if (vbox2 != null)
{
lh.Add(vbox2);
ncolors++;
}
lh.Sort(comparator);
if(ncolors >= target)
if (ncolors >= target)
{
return;
}
if(niters++ > MaxIterations)
if (niters++ > MaxIterations)
{
return;
}
@@ -318,7 +318,7 @@ namespace ColorThiefDotNet
public static CMap Quantize(byte[][] pixels, int maxcolors)
{
// short-circuit
if(pixels.Length == 0 || maxcolors < 2 || maxcolors > 256)
if (pixels.Length == 0 || maxcolors < 2 || maxcolors > 256)
{
return null;
}
@@ -327,7 +327,7 @@ namespace ColorThiefDotNet
// get the beginning vbox from the colors
var vbox = VboxFromPixels(pixels, histo);
var pq = new List<VBox> {vbox};
var pq = new List<VBox> { vbox };
// Round up to have the same behaviour as in JavaScript
var target = (int)Math.Ceiling(FractByPopulation * maxcolors);
@@ -347,7 +347,7 @@ namespace ColorThiefDotNet
// calculate the actual colors
var cmap = new CMap();
foreach(var vb in pq)
foreach (var vb in pq)
{
cmap.Push(vb);
}
@@ -367,7 +367,7 @@ namespace ColorThiefDotNet
double sum = 0;
double sumWeight = 0;
for(var i = 0; i < values.Length; i += 2)
for (var i = 0; i < values.Length; i += 2)
{
var value = values[i];
var weight = values[i + 1];

View File

@@ -33,7 +33,7 @@ namespace ColorThiefDotNet
public int Volume(bool force)
{
if(volume == null || force)
if (volume == null || force)
{
volume = (R2 - R1 + 1) * (G2 - G1 + 1) * (B2 - B1 + 1);
}
@@ -43,18 +43,18 @@ namespace ColorThiefDotNet
public int Count(bool force)
{
if(count == null || force)
if (count == null || force)
{
var npix = 0;
int i;
for(i = R1; i <= R2; i++)
for (i = R1; i <= R2; i++)
{
int j;
for(j = G1; j <= G2; j++)
for (j = G1; j <= G2; j++)
{
int k;
for(k = B1; k <= B2; k++)
for (k = B1; k <= B2; k++)
{
var index = Mmcq.GetColorIndex(i, j, k);
npix += histo[index];
@@ -75,7 +75,7 @@ namespace ColorThiefDotNet
public int[] Avg(bool force)
{
if(avg == null || force)
if (avg == null || force)
{
var ntot = 0;
@@ -85,13 +85,13 @@ namespace ColorThiefDotNet
int i;
for(i = R1; i <= R2; i++)
for (i = R1; i <= R2; i++)
{
int j;
for(j = G1; j <= G2; j++)
for (j = G1; j <= G2; j++)
{
int k;
for(k = B1; k <= B2; k++)
for (k = B1; k <= B2; k++)
{
var histoindex = Mmcq.GetColorIndex(i, j, k);
var hval = histo[histoindex];
@@ -103,7 +103,7 @@ namespace ColorThiefDotNet
}
}
if(ntot > 0)
if (ntot > 0)
{
avg = new[]
{