diff --git a/LegoArt/MainWindow.xaml b/LegoArt/MainWindow.xaml
index a35584c..e8fbe00 100644
--- a/LegoArt/MainWindow.xaml
+++ b/LegoArt/MainWindow.xaml
@@ -22,6 +22,10 @@
+
+
+
+
diff --git a/LegoArt/MainWindow.xaml.cs b/LegoArt/MainWindow.xaml.cs
index c2a89cf..0f397c4 100644
--- a/LegoArt/MainWindow.xaml.cs
+++ b/LegoArt/MainWindow.xaml.cs
@@ -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,15 @@ 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;
+ var outputPath = BuildingInstructionService.PersistBuildingInstructions(bitmap, tbImagePath.Text);
+ MessageBox.Show($"Instructions saved to {outputPath}", "Saved", MessageBoxButton.OK, MessageBoxImage.Information);
+
+ }
+
private void LoadImage(string path)
{
var bitmap = new System.Drawing.Bitmap(path);
@@ -61,9 +73,11 @@ namespace LegoArt
var sourceBitmap = bitmapHelperService.Scale(reducedBitMap, 1);
sourceImage.Source = imageHelperService.LoadToImage(sourceBitmap);
- var convertedBitmap = bitmapHelperService.ConvertToPixelMatrix(sourceBitmap, 20);
+ var convertedBitmap = bitmapHelperService.ConvertToPixelMatrix(sourceBitmap, legoArtColorService.GetLegoColors());
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);
diff --git a/LegoArtTool/BitmapHelperService.cs b/LegoArtTool/BitmapHelperService.cs
index cdf4af0..7d979ce 100644
--- a/LegoArtTool/BitmapHelperService.cs
+++ b/LegoArtTool/BitmapHelperService.cs
@@ -1,4 +1,5 @@
using LegoArtTool.Pixels;
+using System.Collections.Generic;
using System.Drawing;
namespace LegoArtTool
@@ -29,9 +30,9 @@ namespace LegoArtTool
return scaledBitmap;
}
- public Bitmap ConvertToPixelMatrix(Bitmap bitmap, int pixelSize)
+ public Bitmap ConvertToPixelMatrix(Bitmap bitmap, List legoArtColors)
{
- var pixelMatrix = new PixelMatrix(pixelSize, bitmap);
+ var pixelMatrix = new PixelMatrix(bitmap, legoArtColors);
return pixelMatrix.ConvertBitmap();
}
}
diff --git a/LegoArtTool/BuildingInstructionService.cs b/LegoArtTool/BuildingInstructionService.cs
new file mode 100644
index 0000000..7c28e1b
--- /dev/null
+++ b/LegoArtTool/BuildingInstructionService.cs
@@ -0,0 +1,49 @@
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+
+namespace LegoArtTool
+{
+ public static class BuildingInstructionService
+ {
+ public static string 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);
+ }
+ }
+
+ return outPutDirectory;
+ }
+
+ 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})";
+ }
+ }
+}
\ No newline at end of file
diff --git a/LegoArtTool/LegoArtImageGenerationService.cs b/LegoArtTool/LegoArtImageGenerationService.cs
index ea9116c..15b605b 100644
--- a/LegoArtTool/LegoArtImageGenerationService.cs
+++ b/LegoArtTool/LegoArtImageGenerationService.cs
@@ -35,19 +35,19 @@ namespace LegoArtTool
var reducedBitmap = new Bitmap(bitmap.Width, bitmap.Height);
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);
-
-
+
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);
- }
}
}
\ No newline at end of file
diff --git a/LegoArtTool/Pixels/GraphicExtensions.cs b/LegoArtTool/Pixels/GraphicExtensions.cs
new file mode 100644
index 0000000..3f3472e
--- /dev/null
+++ b/LegoArtTool/Pixels/GraphicExtensions.cs
@@ -0,0 +1,42 @@
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace LegoArtTool.Pixels
+{
+ public static class GraphicsExtensions
+ {
+ public static void DrawCircle(this Graphics g, Pen pen, float centerX, float centerY, float radius)
+ {
+ g.DrawEllipse(pen, centerX - radius, centerY - radius, radius + radius, radius + radius);
+ }
+
+ public static void FillCircle(this Graphics g, Brush brush, float centerX, float centerY, float radius)
+ {
+ g.FillEllipse(brush, centerX - radius, centerY - radius, radius + radius, radius + radius);
+ }
+
+ public static void DrawText(this Graphics g, Brush brush, Font font, int size, StringAlignment alignment, string text)
+ {
+ var format = new StringFormat();
+ format.LineAlignment = alignment;
+ format.Alignment = alignment;
+
+ var rectf = new RectangleF(0, 0, size, size);
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ g.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ g.DrawString(text, font, brush, rectf, format);
+ }
+
+ public static Font GetIdealFontSize(this Graphics g, int size, string referenceText, Font preferedFont)
+ {
+ var room = new Size(size, size);
+ var realSize = g.MeasureString(referenceText, preferedFont);
+ var heightScaleRatio = room.Height / realSize.Height;
+ var widthScaleRatio = room.Width / realSize.Width;
+ var scaleRatio = (heightScaleRatio < widthScaleRatio) ? heightScaleRatio : widthScaleRatio;
+ var scaleFontSize = preferedFont.Size * scaleRatio;
+ return new Font(preferedFont.FontFamily, scaleFontSize);
+ }
+ }
+}
diff --git a/LegoArtTool/Pixels/Pixel.cs b/LegoArtTool/Pixels/Pixel.cs
index 5aba4ee..1ddc3d2 100644
--- a/LegoArtTool/Pixels/Pixel.cs
+++ b/LegoArtTool/Pixels/Pixel.cs
@@ -6,27 +6,42 @@ namespace LegoArtTool.Pixels
{
public Color Color { get; private set; }
public int Number { get; private set; }
- public int Size { get; private set; }
- public Pixel(Color color, int size, int number)
+ public const int PixelSize = 50;
+ private const int NumberSize = 20;
+
+ public Pixel(Color color, int number)
{
Color = color;
- Size = size;
Number = number;
}
public Bitmap GetBitmap()
{
- var bitmap = new Bitmap(Size, Size);
- for (int x = 0; x < Size; x++)
+ var bitmap = new Bitmap(PixelSize, PixelSize);
+ for (int x = 0; x < PixelSize; x++)
{
- for (int y = 0; y < Size; y++)
+ for (int y = 0; y < PixelSize; y++)
{
bitmap.SetPixel(x, y, Color);
}
}
+ DrawNumber(bitmap, Number);
+
return bitmap;
}
+
+ private void DrawNumber(Bitmap bitmap, int number)
+ {
+
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.FillCircle(Brushes.White, PixelSize / 2, PixelSize / 2, NumberSize / 2);
+ var font = g.GetIdealFontSize(NumberSize, "15", new Font("Arial", 8));
+ g.DrawText(Brushes.Black, font, PixelSize, StringAlignment.Center, number.ToString());
+ g.Flush();
+ }
+ }
}
}
diff --git a/LegoArtTool/Pixels/PixelMatrix.cs b/LegoArtTool/Pixels/PixelMatrix.cs
index 10317b2..2a709db 100644
--- a/LegoArtTool/Pixels/PixelMatrix.cs
+++ b/LegoArtTool/Pixels/PixelMatrix.cs
@@ -1,5 +1,7 @@
using System;
+using System.Collections.Generic;
using System.Drawing;
+using System.Linq;
namespace LegoArtTool.Pixels
{
@@ -7,14 +9,12 @@ namespace LegoArtTool.Pixels
{
public Pixel[,] Pixels { get; private set; }
public int MatrixSize { get; private set; }
- public int PixelSize { get; private set; }
private Random rnd = new Random();
- public PixelMatrix(int pixelSize, Bitmap sourceBitmap)
+ public PixelMatrix(Bitmap sourceBitmap, List legoArtColors)
{
MatrixSize = sourceBitmap.Width;
- PixelSize = pixelSize;
Pixels = new Pixel[MatrixSize, MatrixSize];
for (int x = 0; x < MatrixSize; x++)
@@ -23,14 +23,15 @@ namespace LegoArtTool.Pixels
{
var pixel = sourceBitmap.GetPixel(x, y);
var sourceColor = Color.FromArgb(pixel.ToArgb());
- Pixels[x, y] = new Pixel(sourceColor, PixelSize, 9);
+ var legoNumber = legoArtColors.Single(l => l.Color == sourceColor).LegoNumber;
+ Pixels[x, y] = new Pixel(sourceColor, legoNumber);
}
}
}
public Bitmap ConvertBitmap()
{
- var bitmapSize = MatrixSize * PixelSize;
+ var bitmapSize = MatrixSize * Pixel.PixelSize;
var bitmap = new Bitmap(bitmapSize, bitmapSize);
using (var g = Graphics.FromImage(bitmap))
{