Created
June 13, 2017 10:35
-
-
Save jmcd/08886dd7a4d247f91ee69f86b7cb6ed3 to your computer and use it in GitHub Desktop.
Create data from a hand drawn bmp line
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Drawing; | |
using System.Linq; | |
namespace Trendy | |
{ | |
internal class Program | |
{ | |
private static void Main(string[] args) | |
{ | |
var filePath = args[0]; | |
var numberOfSamples = args.ElementAtOrDefault(1).ParseInt() ?? 100; | |
var opMax = args.ElementAtOrDefault(2).ParseDouble() ?? 1; | |
var opMin = args.ElementAtOrDefault(3).ParseDouble() ?? 0; | |
var opDelta = opMax - opMin; | |
var bitmap = new Bitmap(filePath); | |
var pixelHeights = PixelHeights(bitmap, IsValue); | |
var pixHeightMin = pixelHeights.Min(); | |
var pixHeightMax = pixelHeights.Max(); | |
var pixDelta = (double) (pixHeightMax - pixHeightMin); | |
var stepSize = pixelHeights.Count / (double) numberOfSamples; | |
for (var i = 0; i < numberOfSamples; i++) | |
{ | |
var valueIndex = (int) stepSize * i; | |
var rawValue = pixelHeights[valueIndex]; | |
var normalizedValue = (rawValue - pixHeightMin) / pixDelta; | |
var outputValue = opMin + normalizedValue * opDelta; | |
Console.WriteLine(outputValue); | |
} | |
} | |
private static List<int> PixelHeights(Bitmap bitmap, Func<Color?, bool> pixelValuePredicate) | |
{ | |
var pixelHeights = new List<int>(bitmap.Width); | |
for (var x = 0; x < bitmap.Width; x++) | |
{ | |
var prevValue = pixelHeights.Any() ? pixelHeights.Last() : default(int?); | |
var bestGuess = prevValue ?? bitmap.Height / 2; | |
var closestYCoord = Tools.SearchRadially(bestGuess, y => bitmap.GetPixelOrNull(x, y), pixelValuePredicate); | |
if (closestYCoord.HasValue) | |
{ | |
pixelHeights.Add(bitmap.FlipY(closestYCoord.Value)); | |
} | |
} | |
return pixelHeights; | |
} | |
private static bool IsValue(Color? color) | |
{ | |
return color?.R == 0 && color?.G == 0 && color?.B == 0; | |
} | |
} | |
internal static class Tools | |
{ | |
internal static int? ParseInt(this string s) | |
{ | |
var r = default(int?); | |
if (Int32.TryParse(s, out int parsed)) | |
{ | |
r = parsed; | |
} | |
return r; | |
} | |
internal static double? ParseDouble(this string s) | |
{ | |
var r = default(double?); | |
if (Double.TryParse(s, out double parsed)) | |
{ | |
r = parsed; | |
} | |
return r; | |
} | |
internal static int FlipY(this Bitmap @this, int y) | |
{ | |
return @this.Height - y; | |
} | |
internal static Color? GetPixelOrNull(this Bitmap @this, int x, int y) | |
{ | |
if (x < 0 || x >= @this.Width || y < 0 || y >= @this.Height) | |
{ | |
return null; | |
} | |
return @this.GetPixel(x, y); | |
} | |
internal static int? SearchRadially<T>(int start, Func<int, T> elementOrNull, Func<T, bool> successPredicate) | |
{ | |
for (var offset = 0;; offset++) | |
{ | |
var leftIndex = start - offset; | |
var rightIndex = start + offset; | |
var left = elementOrNull(leftIndex); | |
var right = elementOrNull(rightIndex); | |
if (left == null && right == null) | |
{ | |
break; | |
} | |
if (successPredicate(left)) | |
{ | |
return leftIndex; | |
} | |
if (successPredicate(right)) | |
{ | |
return rightIndex; | |
} | |
} | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment