/// <summary> /// Normalizes the highest component to a value of max, the /// lowest component to a value of min, adjusts the other /// values accordingly. No effect on alpha. /// Color (0.1, 0.8, 0.9) mapped as (0, 1) -> Color (0, 0.96, 1) /// Color (0.1, 0.8, 0.9) mapped as (0.4, 0.6) -> (0.42, 0.56, 0.58) /// </summary> public static Color Normalize(Color color, float min = 0, float max = 1.0f) { float maxRGB = color.Max(); float minRGB = color.Min(); color.r = PMath.Map(color.r, minRGB, maxRGB, min, max); color.g = PMath.Map(color.g, minRGB, maxRGB, min, max); color.b = PMath.Map(color.b, minRGB, maxRGB, min, max); return(color); }
public float Value(float a) { var xOff = PMath.Map(PMath.Cos(a), -1, 1, CenterX, Diameter + CenterX); var yOff = PMath.Map(PMath.Sin(a), -1, 1, CenterY, Diameter + CenterY); SetNoiseType(NoiseType.PerlinFractal); SetInterp(Interp.Quintic); SetFractalType(FractalType.RigidMulti); SetFractalLacunarity(3); SetFrequency(0.1f); var r = GetNoise(xOff, yOff); return(PMath.Map(r, -0.5f, 0.5f, Min, Max)); }
public void Map_ClampsOutOfBoundValues() { // arrange float r = 1; // scale 0,1 -> scale 4,3 float g = 5; // scale 10,5 -> scale 0,1 float b = -7; // scale -10,0 -> scale 10,0 // act r = PMath.Map(r, 0, 0.5f, 3, 5); g = PMath.Map(g, 0, 1, 3, 9); b = PMath.Map(b, 0, 15, 2, 99); // assert Assert.AreEqual(5, r); Assert.AreEqual(9, g); Assert.AreEqual(2, b); }
public void Map_ConvertsNegativeRanges() { // arrange float r = -1; // scale 0,1 -> scale 4,3 float g = -7.5f; // scale 10,5 -> scale 0,1 float b = -7; // scale -10,0 -> scale 10,0 // act r = PMath.Map(r, -10, 0, 0, 10); g = PMath.Map(g, -10, -5, 0, 10); b = PMath.Map(b, -7, 3, 1, 10); // assert Assert.AreEqual(9, r); Assert.AreEqual(5, g); Assert.AreEqual(1, b); }
public void Map_IgnoresIncorrectMinMaxOrder() { // arrange float r = 0.65f; // scale 0,1 -> scale 4,3 float g = 7.5f; // scale 10,5 -> scale 0,1 float b = 7; // scale -10,0 -> scale 10,0 // act r = PMath.Map(r, 0, 1, 4, 3); g = PMath.Map(g, 10, 5, 0, 1); b = PMath.Map(b, 10, 0, 1, 0); // assert Assert.AreEqual(3.65f, r); Assert.AreEqual(0.5f, g); Assert.AreEqual(0.7f, b); }
public void Map_ReturnsShiftedValue() { // arrange float r = 1; // scale 0,1 -> scale 3,4 float g = 5; // scale 1,10 -> scale 11,20 float b = -7; // scale -10,0 -> scale -5,5 // act r = PMath.Map(r, 0, 1, 3, 4); g = PMath.Map(g, 1, 10, 11, 20); b = PMath.Map(b, -10, 0, -5, 5); // assert Assert.AreEqual(4, r); Assert.AreEqual(15, g); Assert.AreEqual(-2, b); }
public void Map_ReturnsExpandedValue() { // arrange float r = 0.9f; // scale 0,1 -> scale 0,10 float g = 5; // scale 1,10 -> scale 1,100 float b = 2; // scale -10,0 -> scale 1,10 // act r = PMath.Map(r, 0, 1, 0, 10); g = PMath.Map(g, 0, 10, 0, 100); b = PMath.Map(b, 0, 3, 0, 9); // assert Assert.AreEqual(9, r, "r: " + TestHelper.ShowVariables(9, r)); Assert.AreEqual(50, g, "g: " + TestHelper.ShowVariables(50, g)); Assert.AreEqual(6, b, "b: " + TestHelper.ShowVariables(6, b)); }
public void Map_ReturnsCompressedValue() { // prereq Approx_Works(); // arrange float r = 1; float g = 5; float b = 7; // act r = PMath.Map(r, 0, 1, 0, 0.5f); // scale 0,1 -> scale 0,0.5 g = PMath.Map(g, 1, 10, 0.1f, 1); // scale 1,10 -> scale 0.1,1 b = PMath.Map(b, 1, 10, 0.5f, 5); // scale -10,0 -> scale 1,5 // assert Assert.IsTrue(PMath.Approx(0.5f, r, 1), "r: " + TestHelper.ShowVariables(0.5f, r)); Assert.IsTrue(PMath.Approx(0.5f, g, 1), "g: " + TestHelper.ShowVariables(0.5f, g)); Assert.IsTrue(PMath.Approx(3.5f, b, 1), "b: " + TestHelper.ShowVariables(3.5f, b)); }
public PColor Convert(PColor i) { i.G -= (int)(i.R * 0.67f); i.G = (int)PMath.Clamp(i.G, 0, 255); i.B -= (int)(i.R * 0.33f); i.B = (int)PMath.Clamp(i.B, 0, 255); i.R = 0; RgbToHls(i.R, i.G, i.B, out var h, out var l, out var s); //h = PMath.Clamp((float)h, 70, 300); //h = PMath.Map((float)h, 0, 360, 20, 280); l = PMath.Clamp((float)l, 0f, 0.3f); //l = PMath.Map((float)l, 0f, 0.3f, 0f, 1f); HlsToRgb(h, l, s, out i.R, out i.G, out i.B); return(new PColor((int)PMath.Map(i.R, 0, 255, 0, i.G + i.B), i.G, i.B)); }
public void Setup() { Console.Write("Enter video framerate: "); var framerate = Console.ReadLine(); Console.Write("Enter total frame count: "); var frames = int.Parse(Console.ReadLine()); Console.Write("Enter output video file name (no extension): "); var name = Console.ReadLine().Trim(); Console.Write("Enter resolution separated by a comma (480,480): "); var res = Console.ReadLine().Split(',').ToList().ConvertAll(resPart => int.Parse(resPart)).ToArray(); Console.Write("Enter mandelbrot power range (x in f(z)=z^x + c) separated by a comma (1,10): "); var range = Console.ReadLine().Split(',').ToList().ConvertAll(rangePart => int.Parse(rangePart)).ToArray(); var s = Stopwatch.StartNew(); Console.WriteLine("Generation is starting, please wait..."); var done = 0; var items = Enumerable.Range(0, frames).ToArray(); var chunks = items .Select((s2, i) => new { Value = s2, Index = i }) .GroupBy(x => x.Index / 10) .Select(grp => grp.Select(x => x.Value).ToArray()).ToList(); var threads = new List <Thread>(); for (var t = 0; t < Environment.ProcessorCount - 1; t++) { var t2 = t; var thread = new Thread(() => { start:; if (chunks.Count == 0) { goto exit; } var assignedChunk = chunks[0]; chunks.RemoveAt(0); foreach (var a in assignedChunk) { var pow = PMath.Map(a, 1, frames, range[0], range[1]); var Image = new PSprite(res[0], res[1]); var pixels = Image.Art.GetPixels(); for (var y = 0; y < Image.Height; y++) { for (var x = 0; x < Image.Width; x++) { var xTarget = 4f; var yTarget = (xTarget / Image.Width) * Image.Height; var x2 = (x / (Image.Width / (xTarget))) - (xTarget / 2); var y2 = (y / (Image.Height / (yTarget))) - (yTarget / 2); var c = new Complex(x2, y2); var z = Complex.Zero; var max = -1f; var maxWasHit = false; for (var i = 0; i < maxDepth; i++) { z = (Complex.Pow(z, pow)) + c; if ((z.Real * z.Real) + (z.Imaginary * z.Imaginary) > 16 && max == -1f) { max = i; maxWasHit = true; break; } } var color = PColor.Black; if (maxWasHit) { var floorMax = (int)Math.Floor(max); var c1 = pallet[floorMax % pallet.Length]; var c2 = pallet[(floorMax + 1) % pallet.Length]; color = PColor.Lerp(c1, c2, 0.5f); } var pos = ((y * Image.Width) + x) * 4; pixels[pos] = (byte)(color.R); pixels[pos + 1] = (byte)(color.G); pixels[pos + 2] = (byte)(color.B); pixels[pos + 3] = 255; } } Image.Art.SetPixels(pixels); Image.Save(folder + a.ToString("000000") + ".png"); var percent = (done / (float)frames); var remaining = (1f - percent) * 100; var secondsPerPercent = s.Elapsed.TotalSeconds / (percent * 100f); var minutesRemaining = ((secondsPerPercent * remaining) / 60f); var estimatedTime = DateTime.Now.AddMinutes(done == 0 ? 0 : minutesRemaining); Console.WriteLine("Progress: " + done + "/" + frames + " " + (percent * 100f).ToString("0.00") + "% Estimated completion time: " + estimatedTime); done++; } goto start; exit:; }) { Name = "Mandelbrot: Core " + (t + 1), Priority = ThreadPriority.AboveNormal, }; threads.Add(thread); thread.Start(); } ; var info = new ProcessStartInfo() { FileName = "ffmpeg", Arguments = string.Format(" -framerate {0} -i %06d.png -c:v libx264 -r {0} {1}.mp4", framerate, name), WorkingDirectory = folder, }; var activeThreads = 1; do { Console.Title = "Active thread count: " + activeThreads; activeThreads = threads.Where(t => t.IsAlive).Count(); Thread.Sleep(1000); Title(activeThreads); }while (activeThreads > 0); Console.Title = "Active thread count: 0"; var p = Process.Start(info); p.WaitForExit(); Console.WriteLine(@"Saved as " + folder + "out.mp4"); Console.ReadLine(); Close(); }