Skip to content

Commit

Permalink
+working on HSV color matching instead of just RGB
Browse files Browse the repository at this point in the history
  • Loading branch information
bahstrike committed Mar 13, 2022
1 parent 17c5e10 commit 596aa1f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 8 deletions.
16 changes: 16 additions & 0 deletions DyeAtlas.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 71 additions & 2 deletions DyeAtlas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void SaveFile(string file)

if(Path.GetExtension(file).Equals(".pnt", StringComparison.InvariantCultureIgnoreCase))//IsFilePNT(file))
{
PNTImage pnt = PNTImage.GenerateFromBitmap(palette, bmp, dithering.Checked);
PNTImage pnt = PNTImage.GenerateFromBitmap(palette, bmp, dithering.Checked, hsvcompare.Checked);

pnt.Save(file);
}else
Expand Down Expand Up @@ -206,7 +206,7 @@ public void OpenFile(string file)
bmp = newBmp;
}

pnt = PNTImage.GenerateFromBitmap(palette, bmp, dithering.Checked);
pnt = PNTImage.GenerateFromBitmap(palette, bmp, dithering.Checked, hsvcompare.Checked);
}
break;
}
Expand Down Expand Up @@ -265,6 +265,11 @@ private void dithering_CheckedChanged(object sender, EventArgs e)
OpenFile(currentfile.Text);
}

private void hsvcompare_CheckedChanged(object sender, EventArgs e)
{
OpenFile(currentfile.Text);
}

private void savePNTButton_Click(object sender, EventArgs e)
{
// dont do popup if image is blank; prolly button should be disabled
Expand Down Expand Up @@ -344,5 +349,69 @@ private void gamechoice_SelectedIndexChanged(object sender, EventArgs e)

OpenFile(currentfile.Text);
}


#region RGB<->HSV
public static class ColorConversion
{
// https://stackoverflow.com/questions/359612/how-to-convert-rgb-color-to-hsv
public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)
{
int max = Math.Max(color.R, Math.Max(color.G, color.B));
int min = Math.Min(color.R, Math.Min(color.G, color.B));

hue = color.GetHue();
saturation = (max == 0) ? 0 : 1d - (1d * min / max);
value = max / 255d;
}

public static Color ColorFromHSV(double hue, double saturation, double value)
{
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);

value = value * 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));

if (hi == 0)
return Color.FromArgb(255, v, t, p);
else if (hi == 1)
return Color.FromArgb(255, q, v, p);
else if (hi == 2)
return Color.FromArgb(255, p, v, t);
else if (hi == 3)
return Color.FromArgb(255, p, q, v);
else if (hi == 4)
return Color.FromArgb(255, t, p, v);
else
return Color.FromArgb(255, v, p, q);
}
}
#endregion

#region AngleDiff
public static class AngleDiff
{
//https://stackoverflow.com/questions/7570808/how-do-i-calculate-the-difference-of-two-angle-measures
/**
* Shortest distance (angular) between two angles.
* It will be in range [0, 180].
*/
public static int distance(int alpha, int beta)
{
int phi = Math.Abs(beta - alpha) % 360; // This is either the distance or 360 - distance
int distance = phi > 180 ? 360 - phi : phi;
return distance;
}

public static double distance(double alpha, double beta)
{
return (double)distance((int)Math.Round(alpha), (int)Math.Round(beta));
}
}
#endregion
}
}
8 changes: 4 additions & 4 deletions PNTImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public PNTImage(Palette _palette)
palette = _palette;
}

public static PNTImage GenerateFromBitmap(Palette pal, Bitmap bmp, bool dither)
public static PNTImage GenerateFromBitmap(Palette pal, Bitmap bmp, bool dither, bool hsvCompare)
{
PNTImage pnt = new PNTImage(pal);
pnt.version = 1;
Expand All @@ -43,7 +43,7 @@ public static PNTImage GenerateFromBitmap(Palette pal, Bitmap bmp, bool dither)
for (int x = 0; x < pnt.width; x++)
{
WorkColor clr = scratch.GetPixel(x, y);
pnt.SetPixel(x, y, clr);
pnt.SetPixel(x, y, clr, hsvCompare);

// if transparent, then no further processing
if (clr.Transparent)
Expand Down Expand Up @@ -125,12 +125,12 @@ public void Save(string file)
return palette.Get(bits[x + y * width]);
}

public void SetPixel(int x, int y, Color clr)
public void SetPixel(int x, int y, Color clr, bool hsvCompare)
{
if (x < 0 || x >= width || y < 0 || y >= height)
return;

bits[x + y * width] = (byte)palette.FindClosestIndex(clr);
bits[x + y * width] = (byte)palette.FindClosestIndex(clr, hsvCompare);
}

public Bitmap GenerateBitmap()
Expand Down
33 changes: 31 additions & 2 deletions Palette.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class PaletteEntry
return null;
}

public int FindClosestIndex(Color clr)
public int FindClosestIndex(Color clr, bool hsvCompare)
{
if (clr.A == 0)
return 0;
Expand All @@ -64,7 +64,36 @@ public int FindClosestIndex(Color clr)
int closestDiff = 99999;
foreach (PaletteEntry pe in entries)
{
int diff = Math.Abs(pe.color.R - clr.R) + Math.Abs(pe.color.G - clr.G) + Math.Abs(pe.color.B - clr.B);
int diff;

if (hsvCompare)
{
double aHue, aSat, aVal;
double bHue, bSat, bVal;
DyeAtlas.ColorConversion.ColorToHSV(pe.color, out aHue, out aSat, out aVal);
DyeAtlas.ColorConversion.ColorToHSV(clr, out bHue, out bSat, out bVal);


double hueDiff = DyeAtlas.AngleDiff.distance(aHue, bHue) / 180.0;
double satDiff = Math.Abs(aSat - bSat);
double valDiff = Math.Abs(aVal - bVal);

// weights
hueDiff *= 1.0;
satDiff *= 1.0;
valDiff *= 1.0;


//quantize, i guess
diff = (int)Math.Round(hueDiff * 100.0) +
(int)Math.Round(satDiff * 100.0) +
(int)Math.Round(valDiff * 100.0);
}
else
{
// RGB compare
diff = Math.Abs(pe.color.R - clr.R) + Math.Abs(pe.color.G - clr.G) + Math.Abs(pe.color.B - clr.B);
}

if (diff < closestDiff)
{
Expand Down

0 comments on commit 596aa1f

Please sign in to comment.