Skip to content

Instantly share code, notes, and snippets.

@jmcd
Created June 13, 2017 10:35
Show Gist options
  • Save jmcd/08886dd7a4d247f91ee69f86b7cb6ed3 to your computer and use it in GitHub Desktop.
Save jmcd/08886dd7a4d247f91ee69f86b7cb6ed3 to your computer and use it in GitHub Desktop.
Create data from a hand drawn bmp line
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