Getting the color filtering working

This commit is contained in:
LarsBrubaker 2021-08-16 09:18:36 -07:00
parent 86ee3b4b9c
commit 93735995b7
2 changed files with 213 additions and 18 deletions

View file

@ -55,7 +55,19 @@ namespace MatterHackers.MatterControl.DesignTools
public event EventHandler EditComplete;
public void RebuildAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage)
public void RebuildAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage, ImageToPathObject3D_2.AnalysisTypes analysisType)
{
if (analysisType == ImageToPathObject3D_2.AnalysisTypes.Colors)
{
RebuildColorToAlphaImage(sourceImage, alphaImage);
}
else
{
RebuildIntensityToAlphaImage(sourceImage, alphaImage);
}
}
private void RebuildIntensityToAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage)
{
if (sourceImage == null)
{
@ -106,12 +118,12 @@ namespace MatterHackers.MatterControl.DesignTools
for (int x = 0; x < sourceImage.Width; x++)
{
int imageBufferOffsetWithX = imageOffset + x * 4;
var r = sourceBuffer[imageBufferOffsetWithX + 0];
var b = sourceBuffer[imageBufferOffsetWithX + 0];
var g = sourceBuffer[imageBufferOffsetWithX + 1];
var b = sourceBuffer[imageBufferOffsetWithX + 2];
destBuffer[imageBufferOffsetWithX + 0] = r;
var r = sourceBuffer[imageBufferOffsetWithX + 2];
destBuffer[imageBufferOffsetWithX + 0] = b;
destBuffer[imageBufferOffsetWithX + 1] = g;
destBuffer[imageBufferOffsetWithX + 2] = b;
destBuffer[imageBufferOffsetWithX + 2] = r;
destBuffer[imageBufferOffsetWithX + 3] = GetAlphaFromIntensity(r, g, b);
}
});
@ -119,17 +131,154 @@ namespace MatterHackers.MatterControl.DesignTools
alphaImage.MarkImageChanged();
}
private static (float hue, float saturation) GetHue(byte bR, byte bG, byte bB)
{
var r = bR / 255.0f;
var g = bG / 255.0f;
var b = bB / 255.0f;
var maxRGB = Math.Max(r, Math.Max(g, b));
var minRGB = Math.Min(r, Math.Min(g, b));
var deltaMaxToMin = maxRGB - minRGB;
float r2, g2, b2;
var lightness0To1 = (minRGB + maxRGB) / 2.0;
if (lightness0To1 <= 0.0)
{
return (0, 0);
}
var saturation0To1 = deltaMaxToMin;
if (saturation0To1 > 0.0)
{
saturation0To1 /= (lightness0To1 <= 0.5f) ? (maxRGB + minRGB) : (2.0f - maxRGB - minRGB);
}
else
{
return (0, 0);
}
r2 = (maxRGB - r) / deltaMaxToMin;
g2 = (maxRGB - g) / deltaMaxToMin;
b2 = (maxRGB - b) / deltaMaxToMin;
var hue0To1 = 0.0f;
if (r == maxRGB)
{
if (g == minRGB)
{
hue0To1 = 5.0f + b2;
}
else
{
hue0To1 = 1.0f - g2;
}
}
else if (g == maxRGB)
{
if (b == minRGB)
{
hue0To1 = 1.0f + r2;
}
else
{
hue0To1 = 3.0f - b2;
}
}
else
{
if (r == minRGB)
{
hue0To1 = 3.0f + g2;
}
else
{
hue0To1 = 5.0f - r2;
}
}
hue0To1 /= 6.0f;
return (hue0To1, saturation0To1);
}
private static byte GetAlphaFromHue(byte r, byte g, byte b, double start, double end)
{
var hs = GetHue(r, g, b);
if (hs.saturation > .6 && hs.hue <= end && hs.hue > start)
{
return 255;
}
return 0;
}
private void RebuildColorToAlphaImage(ImageBuffer sourceImage, ImageBuffer alphaImage)
{
if (sourceImage == null)
{
return;
}
// build the alpha image
if (alphaImage == null)
{
alphaImage = new ImageBuffer(sourceImage.Width, sourceImage.Height);
}
else if (alphaImage.Width != sourceImage.Width
|| alphaImage.Height != sourceImage.Height)
{
alphaImage.Allocate(sourceImage.Width, sourceImage.Height, sourceImage.BitDepth, sourceImage.GetRecieveBlender());
}
byte[] sourceBuffer = sourceImage.GetBuffer();
byte[] destBuffer = alphaImage.GetBuffer();
//Parallel.For(0, sourceImage.Height, (y) =>
for(int y = 0; y < sourceImage.Height; y++)
{
int imageOffset = sourceImage.GetBufferOffsetY(y);
for (int x = 0; x < sourceImage.Width; x++)
{
int imageBufferOffsetWithX = imageOffset + x * 4;
var b = sourceBuffer[imageBufferOffsetWithX + 0];
var g = sourceBuffer[imageBufferOffsetWithX + 1];
var r = sourceBuffer[imageBufferOffsetWithX + 2];
destBuffer[imageBufferOffsetWithX + 0] = b;
destBuffer[imageBufferOffsetWithX + 1] = g;
destBuffer[imageBufferOffsetWithX + 2] = r;
destBuffer[imageBufferOffsetWithX + 3] = GetAlphaFromHue(r, g, b, RangeStart, RangeEnd);
}
}
//});
alphaImage.MarkImageChanged();
}
class QuickHue : IThresholdFunction
{
public Color ZeroColor => throw new NotImplementedException();
public double Threshold(Color color)
{
throw new NotImplementedException();
}
public double Transform(Color color)
{
return GetHue(color.red, color.green, color.blue).hue;
}
}
public void BuildHistogramFromImage(ImageBuffer image, ImageToPathObject3D_2.AnalysisTypes analysisType)
{
// build the histogram cache
var height = (int)(100 * GuiWidget.DeviceScale);
_histogramRawCache = new ImageBuffer(256, height);
var counts = new int[_histogramRawCache.Width];
IThresholdFunction function = new MapOnMaxIntensity(RangeStart, RangeEnd);
IThresholdFunction function = new MapOnMaxIntensity(0, 1);
var bottom = 0;
if (analysisType == ImageToPathObject3D_2.AnalysisTypes.Colors)
{
function = new HueThresholdFunction(RangeStart, RangeEnd);
function = new QuickHue();
bottom = (int)(10 * GuiWidget.DeviceScale);
}
@ -158,9 +307,10 @@ namespace MatterHackers.MatterControl.DesignTools
graphShape.MoveTo(0, bottom);
for (int i = 0; i < 256; i++)
{
graphShape.LineTo(i, bottom + Easing.Exponential.Out(counts[i] / max) * graphHeight);
graphShape.LineTo(i, bottom + counts[i] * graphHeight / max );
}
graphShape.LineTo(image.Width, bottom);
graphShape.LineTo(256, bottom);
graphShape.LineTo(0, bottom);
graphics.Render(graphShape, 0, 0, theme.TextColor);
for(int i=0; i<256; i++)
@ -296,6 +446,51 @@ namespace MatterHackers.MatterControl.DesignTools
}
};
// grabing the center
bool centerDown = false;
var centerX = 0.0;
histogramBackground.MouseDown += (s, e) =>
{
if (e.Button == MouseButtons.Left)
{
centerDown = true;
centerX = e.Position.X;
}
};
histogramBackground.MouseMove += (s, e) =>
{
if (centerDown)
{
var offset = e.Position.X - centerX;
var newEnd = RangeEnd + offset / _histogramRawCache.Width;
newEnd = agg_basics.Clamp(newEnd, RangeStart, 1);
var newStart = RangeStart + offset / _histogramRawCache.Width;
newStart = agg_basics.Clamp(newStart, 0, newEnd);
if (RangeStart != newStart
&& RangeEnd != newEnd)
{
RangeStart = newStart;
RangeEnd = newEnd;
leftHandle.Position = new Vector2(RangeStart * _histogramRawCache.Width, 0);
rightHandle.Position = new Vector2(RangeEnd * _histogramRawCache.Width + handleWidth, 0);
RangeChanged?.Invoke(this, null);
histogramBackground.Invalidate();
}
}
};
histogramBackground.MouseUp += (s, e) =>
{
if (centerDown)
{
centerDown = false;
EditComplete?.Invoke(this, null);
}
};
return histogramWidget;
}
}

View file

@ -83,7 +83,7 @@ namespace MatterHackers.MatterControl.DesignTools
Histogram.BuildHistogramFromImage(SourceImage, AnalysisType);
Histogram.RangeChanged += (s, e) =>
{
Histogram.RebuildAlphaImage(SourceImage, _image);
Histogram.RebuildAlphaImage(SourceImage, _image, AnalysisType);
};
Histogram.EditComplete += (s, e) =>
@ -94,7 +94,7 @@ namespace MatterHackers.MatterControl.DesignTools
switch (AnalysisType)
{
case AnalysisTypes.Intensity:
Histogram.RebuildAlphaImage(SourceImage, _image);
Histogram.RebuildAlphaImage(SourceImage, _image, AnalysisType);
break;
case AnalysisTypes.Transparency:
@ -132,13 +132,9 @@ namespace MatterHackers.MatterControl.DesignTools
switch (AnalysisType)
{
case AnalysisTypes.Intensity:
Histogram.BuildHistogramFromImage(sourceImage, AnalysisType);
Histogram.RebuildAlphaImage(sourceImage, Image);
break;
case AnalysisTypes.Colors:
Histogram.BuildHistogramFromImage(sourceImage, AnalysisType);
Histogram.RebuildAlphaImage(sourceImage, Image);
Histogram.RebuildAlphaImage(sourceImage, Image, AnalysisType);
break;
case AnalysisTypes.Transparency:
@ -246,8 +242,11 @@ namespace MatterHackers.MatterControl.DesignTools
&& invalidateArgs.Source != this
&& !RebuildLocked)
{
Histogram.BuildHistogramFromImage(SourceImage, AnalysisType);
Histogram.RebuildAlphaImage(SourceImage, _image);
if (AnalysisType != AnalysisTypes.Transparency)
{
Histogram.BuildHistogramFromImage(SourceImage, AnalysisType);
Histogram.RebuildAlphaImage(SourceImage, _image, AnalysisType);
}
await Rebuild();
}
else if ((invalidateArgs.InvalidateType.HasFlag(InvalidateType.Properties) && invalidateArgs.Source == this))
@ -288,6 +287,7 @@ namespace MatterHackers.MatterControl.DesignTools
new AlphaFunction());
break;
case AnalysisTypes.Colors:
case AnalysisTypes.Intensity:
this.GenerateMarchingSquaresAndLines(
(progress0to1, status) =>