persist instructions
This commit is contained in:
parent
21395633d2
commit
056e58a297
4 changed files with 78 additions and 44 deletions
|
|
@ -23,6 +23,10 @@
|
|||
<Button Width="50" Name="btnImageChooser" Content="..." Click="btnImageChooser_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Height="25" VerticalAlignment="Top" Margin="5, 0 , 0, 0">
|
||||
<Button Width="200" Name="btnInstructionsPersister" Content="Save Instructions" Click="btnInstructionsPersister_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Vertical" Name="parentStackPanel" VerticalAlignment="Top">
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal">
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
using LegoArtTool;
|
||||
using System.Drawing;
|
||||
using LegoArtTool;
|
||||
using Microsoft.Win32;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using Rectangle = System.Windows.Shapes.Rectangle;
|
||||
|
||||
namespace LegoArt
|
||||
{
|
||||
|
|
@ -17,7 +18,7 @@ namespace LegoArt
|
|||
private readonly LegoArtColorService legoArtColorService;
|
||||
private readonly BitmapHelperService bitmapHelperService;
|
||||
private readonly ImageHelperService imageHelperService;
|
||||
private LegoArtImageGenerationService legoArtImageGenerationService;
|
||||
private readonly LegoArtImageGenerationService legoArtImageGenerationService;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
|
|
@ -27,6 +28,8 @@ namespace LegoArt
|
|||
bitmapHelperService = new BitmapHelperService();
|
||||
imageHelperService = new ImageHelperService();
|
||||
legoArtImageGenerationService = new LegoArtImageGenerationService();
|
||||
|
||||
btnInstructionsPersister.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void btnImageChooser_Click(object sender, RoutedEventArgs e)
|
||||
|
|
@ -50,6 +53,13 @@ namespace LegoArt
|
|||
}
|
||||
}
|
||||
|
||||
private void btnInstructionsPersister_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var d = new DataObject(DataFormats.Bitmap, scaledImage.Source, true);
|
||||
var bitmap = d.GetData(typeof(Bitmap)) as Bitmap;
|
||||
BuildingInstructionService.PersistBuildingInstructions(bitmap, tbImagePath.Text);
|
||||
}
|
||||
|
||||
private void LoadImage(string path)
|
||||
{
|
||||
var bitmap = new System.Drawing.Bitmap(path);
|
||||
|
|
@ -64,6 +74,8 @@ namespace LegoArt
|
|||
var convertedBitmap = bitmapHelperService.ConvertToPixelMatrix(sourceBitmap, 20);
|
||||
scaledImage.Source = imageHelperService.LoadToImage(convertedBitmap);
|
||||
|
||||
btnInstructionsPersister.Visibility = Visibility.Visible;
|
||||
|
||||
parentStackPanel.Children.Clear();
|
||||
|
||||
AddLine(System.Drawing.Color.White, "Have", "Needed", "RGB", "#", "Difference", System.Drawing.Color.White);
|
||||
|
|
|
|||
47
LegoArtTool/BuildingInstructionService.cs
Normal file
47
LegoArtTool/BuildingInstructionService.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
|
||||
namespace LegoArtTool
|
||||
{
|
||||
public class BuildingInstructionService
|
||||
{
|
||||
public static void PersistBuildingInstructions(Bitmap bitmap, string path)
|
||||
{
|
||||
var segmentSize = bitmap.Width / 3;
|
||||
var outPutDirectory = CreateOutPutDirectory(path);
|
||||
|
||||
var segmentNumber = 1;
|
||||
for (var h = 0; h < 3; h++)
|
||||
{
|
||||
for (var w = 0; w < 3; w++)
|
||||
{
|
||||
var rectangle = new Rectangle(w * segmentSize, h * segmentSize, segmentSize, segmentSize);
|
||||
var segment = bitmap.Clone(rectangle, bitmap.PixelFormat);
|
||||
segment.Save($"{outPutDirectory}/{segmentNumber++}.png", ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreateOutPutDirectory(string path)
|
||||
{
|
||||
var increment = 0;
|
||||
|
||||
while (Directory.Exists(GetOutputDirectoryPath(increment, path)))
|
||||
{
|
||||
increment++;
|
||||
}
|
||||
|
||||
var outputDirectoryPath = GetOutputDirectoryPath(increment, path);
|
||||
Directory.CreateDirectory(outputDirectoryPath);
|
||||
return outputDirectoryPath;
|
||||
}
|
||||
|
||||
private static string GetOutputDirectoryPath(int increment, string path)
|
||||
{
|
||||
var parent = Directory.GetParent(path);
|
||||
var filename = Path.GetFileNameWithoutExtension(path);
|
||||
return increment == 0 ? $"{parent}/legoArtInstructions" : $"{parent}/legoArtInstructions_{filename} ({increment})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,17 +36,17 @@ namespace LegoArtTool
|
|||
|
||||
var remainingColors = legoArtColorInfos.ToDictionary(k => k.LegoNumber, v => v.HaveCount);
|
||||
|
||||
|
||||
while (pixels.Count(p => !p.IsAssigned) > 0)
|
||||
{
|
||||
var minOffset = pixels.Where(p => !p.IsAssigned).SelectMany(p => p.LegoArtColorOffsets.Where(o => o.IsAvailable)
|
||||
.Select(o => o.ColorOffset))
|
||||
.Min(x => x);
|
||||
|
||||
var pixel = pixels.Where(p => !p.IsAssigned).First(p => p.LegoArtColorOffsets.Any(o => o.ColorOffset == minOffset));
|
||||
var pixel = pixels.Where(p => !p.IsAssigned).First(p => p.LegoArtColorOffsets.Where(o => o.IsAvailable)
|
||||
.Any(o => o.ColorOffset == minOffset));
|
||||
var legoArtColorInfo = pixel.LegoArtColorOffsets.First(o => o.ColorOffset == minOffset).LegoArtColorInfo;
|
||||
reducedBitmap.SetPixel(pixel.X, pixel.Y, legoArtColorInfo.Color);
|
||||
|
||||
reducedBitmap.SetPixel(pixel.X, pixel.Y, legoArtColorInfo.Color);
|
||||
|
||||
remainingColors[legoArtColorInfo.LegoNumber]--;
|
||||
pixel.IsAssigned = true;
|
||||
|
|
@ -62,50 +62,21 @@ namespace LegoArtTool
|
|||
return reducedBitmap;
|
||||
}
|
||||
|
||||
private Pixel MapPixel(
|
||||
Color inputColor,
|
||||
int xPosition,
|
||||
int yPosition)
|
||||
private Pixel MapPixel(Color inputColor, int xPosition, int yPosition)
|
||||
{
|
||||
var legoArtColorOffsets = legoArtColorInfos.Select(i => ColorOffset(inputColor, i)).ToList();
|
||||
var legoArtColorOffsets = legoArtColorInfos.Select(i => ColorDistance(inputColor, i)).ToList();
|
||||
return new Pixel(xPosition, yPosition, legoArtColorOffsets);
|
||||
}
|
||||
|
||||
private static LegoArtColorOffset ColourDistance(Color inputColor, LegoArtColorInfo colorInfo)
|
||||
private static LegoArtColorOffset ColorDistance(Color inputColor, LegoArtColorInfo colorInfo)
|
||||
{
|
||||
var targetColor = colorInfo.Color;
|
||||
var rmean = ((long)inputColor.R + (long)targetColor.R) / 2;
|
||||
var r = (long)inputColor.R - (long)targetColor.R;
|
||||
var g = (long)inputColor.G - (long)targetColor.G;
|
||||
var b = (long)inputColor.B - (long)targetColor.B;
|
||||
var rmean = (inputColor.R + (long)targetColor.R) / 2;
|
||||
var r = inputColor.R - (long)targetColor.R;
|
||||
var g = inputColor.G - (long)targetColor.G;
|
||||
var b = inputColor.B - (long)targetColor.B;
|
||||
var offset = (decimal) Math.Sqrt((((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8));
|
||||
return new LegoArtColorOffset((decimal) offset, colorInfo);
|
||||
}
|
||||
|
||||
private LegoArtColorOffset ColorOffset(Color inputColor, LegoArtColorInfo colorInfo)
|
||||
{
|
||||
var offset = Math.Abs(
|
||||
ColorNum(inputColor) - ColorNum(colorInfo.Color)) +
|
||||
GetHueDistance(inputColor.GetHue(), colorInfo.Color.GetHue());
|
||||
|
||||
return new LegoArtColorOffset((decimal) offset, colorInfo);
|
||||
}
|
||||
|
||||
private static float GetBrightness(Color c)
|
||||
{
|
||||
return (c.R * 0.299f + c.G * 0.587f + c.B *0.114f) / 256f;
|
||||
}
|
||||
|
||||
private static float GetHueDistance(float hue1, float hue2)
|
||||
{
|
||||
var d = Math.Abs(hue1 - hue2);
|
||||
return d > 180 ? 360 - d : d;
|
||||
|
||||
}
|
||||
|
||||
private static float ColorNum(Color c)
|
||||
{
|
||||
return c.GetSaturation() + GetBrightness(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue