public void ImageShouldBeOverlayedByFilledPolygon() { string path = this.CreateOutputDirectory("Drawing", "FilledBezier"); SixLabors.Primitives.PointF[] simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) }; using (Image <Rgba32> image = new Image <Rgba32>(500, 500)) { image .BackgroundColor(Rgba32.Blue) .Fill(Rgba32.HotPink, new Polygon(new CubicBezierLineSegment(simplePath))) .Save($"{path}/Simple.png"); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { Assert.Equal(Rgba32.HotPink, sourcePixels[150, 300]); //curve points should not be never be set Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); // inside shape should not be empty Assert.Equal(Rgba32.HotPink, sourcePixels[200, 250]); } } }
public void ImageShouldBeOverlayedByFilledPolygonOpacity() { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); var simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); using (var image = new Image <Rgba32>(500, 500)) { image.Mutate(x => x .BackgroundColor(Rgba32.Blue) .FillPolygon(color, simplePath)); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount var mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); } } }
public void ImageShouldBeOverlayedByFilledPolygonNoAntialias() { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); SixLabors.Primitives.PointF[] simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; using (Image <Rgba32> image = new Image <Rgba32>(500, 500)) { image.Mutate(x => x .BackgroundColor(Rgba32.Blue) .FillPolygon(Rgba32.HotPink, simplePath, new GraphicsOptions(false))); image.Save($"{path}/Simple_NoAntialias.png"); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); Assert.Equal(Rgba32.HotPink, sourcePixels[199, 150]); Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); } } }
public void ImageShouldBeOverlayedByFilledPolygonNoAntialias() { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); var simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; using (var image = new Image <Rgba32>(500, 500)) { image.Mutate( x => x.BackgroundColor(Rgba32.Blue).FillPolygon( new GraphicsOptions(false), Rgba32.HotPink, simplePath)); image.Save($"{path}/Simple_NoAntialias.png"); Buffer2D <Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Assert.True(Rgba32.HotPink == sourcePixels[11, 11], "[11, 11] wrong"); Assert.True(Rgba32.HotPink == sourcePixels[199, 149], "[199, 149] wrong"); Assert.True(Rgba32.HotPink == sourcePixels[50, 50], "[50, 50] wrong"); Assert.True(Rgba32.Blue == sourcePixels[2, 2], "[2, 2] wrong"); } }
public void ImageShouldBeOverlayedByFilledPolygonOpacity() { string path = this.CreateOutputDirectory("Drawing", "FilledBezier"); SixLabors.Primitives.PointF[] simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) }; Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); using (Image <Rgba32> image = new Image <Rgba32>(500, 500)) { image .BackgroundColor(Rgba32.Blue) .Fill(color, new Polygon(new CubicBezierLineSegment(simplePath))) .Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { //top of curve Assert.Equal(mergedColor, sourcePixels[138, 116]); //curve points should not be never be set Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); // inside shape should not be empty Assert.Equal(mergedColor, sourcePixels[200, 250]); } } }
static PointF Offset(PointF point, SizeF direction, float distance) { return(new PointF() { X = point.X + direction.Width * distance, Y = point.Y + direction.Height * distance, }); }
public override Image Render(string mode = "human") { float b, t, r, l; const int screen_width = 600; const int screen_height = 400; const float world_width = x_threshold * 2; const float scale = screen_width / world_width; const int carty = 300; const float polewidth = 10.0f; const float poleheight = scale * (2 * length); const float cartwidth = 50.0f; const float cartheight = 30.0f; if (_viewer == null) { lock (this) { //to prevent double initalization. if (_viewer == null) { if (_viewerFactory == null) { _viewerFactory = NullEnvViewer.Factory; } _viewer = _viewerFactory(screen_width, screen_height, "cartpole-v1"); } } } //pole l = -polewidth / 2; r = polewidth / 2; t = poleheight - polewidth / 2; b = -polewidth / 2; var pole = new RectangularPolygon(-polewidth / 2, carty - poleheight, polewidth, poleheight); var circle = new EllipsePolygon(0, carty - polewidth / 2, polewidth / 2); //cart l = -cartwidth / 2; r = cartwidth / 2; t = cartheight / 2; b = -cartheight / 2; var axleoffset = cartheight / 4.0; var cart = new RectangularPolygon(-cartwidth / 2, carty - cartheight / 2, cartwidth, cartheight); var draw = new List <(IPath, Rgba32)>(); if (!(state is null)) { var center_x = (float)(state.GetDouble(0) * scale + screen_width / 2.0f); //no y cuz it doesnt change. var cbounds = circle.Bounds; var pivotPoint = new PointF(cbounds.X + cbounds.Width / 2f, cbounds.Y + cbounds.Height / 2f); draw.Add((cart.Translate(center_x, 0), Rgba32.Black)); draw.Add((pole.Transform(Matrix3x2.CreateRotation((float)state.GetDouble(2), pivotPoint)).Translate(center_x, 0), new Rgba32(204, 153, 102))); draw.Add((circle.Translate(center_x, 0), Rgba32.Teal)); }
private void Render(int lineCount) { Stopwatch stopwatch = Stopwatch.StartNew(); using (var image = new Image <SixLabors.ImageSharp.PixelFormats.Rgba32>(600, 400)) { image.Mutate(imageContext => { // draw background var bgColor = SixLabors.ImageSharp.PixelFormats.Rgba32.FromHex("#003366"); imageContext.BackgroundColor(bgColor); for (int i = 0; i < lineCount; i++) { // create an array of two points to make the straight line var points = new SixLabors.Primitives.PointF[2]; points[0] = new SixLabors.Primitives.PointF( x: (float)(rand.NextDouble() * pictureBox1.Width), y: (float)(rand.NextDouble() * pictureBox1.Height)); points[1] = new SixLabors.Primitives.PointF( x: (float)(rand.NextDouble() * pictureBox1.Width), y: (float)(rand.NextDouble() * pictureBox1.Height)); // create a pen unique to this line var lineColor = SixLabors.ImageSharp.Color.FromRgba( r: (byte)rand.Next(255), g: (byte)rand.Next(255), b: (byte)rand.Next(255), a: (byte)rand.Next(255)); float lineWidth = rand.Next(1, 10); var linePen = new SixLabors.ImageSharp.Processing.Pen(lineColor, lineWidth); // draw the line imageContext.DrawLines(linePen, points); } }); // render onto an Image var stream = new System.IO.MemoryStream(); image.SaveAsBmp(stream); System.Drawing.Image img = System.Drawing.Image.FromStream(stream); pictureBox1.Image?.Dispose(); pictureBox1.Image = img; } stopwatch.Stop(); renderTimesMsec.Add(1000.0 * stopwatch.ElapsedTicks / Stopwatch.Frequency); double mean = renderTimesMsec.Sum() / renderTimesMsec.Count(); Debug.WriteLine($"Render {renderTimesMsec.Count:00} " + $"took {renderTimesMsec.Last():0.000} ms " + $"(running mean: {mean:0.000} ms)"); Application.DoEvents(); }
static SizeF Vector(PointF start, PointF end) { var dx = end.X - start.X; var dy = end.Y - start.Y; var length = Math.Sqrt(dx * dx + dy * dy); return(new SizeF() { Width = (float)(dx / length), Height = (float)(dy / length) }); }
public void ImageShouldBeOverlayedByFilledPolygonWithPattern() { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); var simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; using (var image = new Image <Rgba32>(500, 500)) { image.Mutate( x => x.FillPolygon(new GraphicsOptions(true), Brushes.Horizontal(Rgba32.HotPink), simplePath)); image.Save($"{path}/Pattern.png"); Buffer2D <Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); } }
public void DrawBeziers <TPixel>(TestImageProvider <TPixel> provider, string colorName, byte alpha, float thickness) where TPixel : struct, IPixel <TPixel> { var points = new SixLabors.Primitives.PointF[] { new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) }; Rgba32 rgba = TestUtils.GetColorByName(colorName); rgba.A = alpha; Color color = rgba; FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; provider.RunValidatingProcessorTest(x => x.DrawBeziers(color, 5f, points), testDetails, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); }
public void ImageShouldBeOverlayedByFilledPolygonImage() { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); var simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; using (Image <Rgba32> brushImage = TestFile.Create(TestImages.Bmp.Car).CreateRgba32Image()) using (var image = new Image <Rgba32>(500, 500)) { var brush = new ImageBrush <Rgba32>(brushImage); image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate(x => x.FillPolygon(brush, simplePath)); image.Save($"{path}/Image.png"); } }
public void FillPolygon_Concave <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { var points = new SixLabors.Primitives.PointF[] { new Vector2(8, 8), new Vector2(64, 8), new Vector2(64, 64), new Vector2(120, 64), new Vector2(120, 120), new Vector2(8, 120) }; var color = Color.LightGreen; provider.RunValidatingProcessorTest( c => c.FillPolygon(color, points), appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); }
public void ImageShouldBeOverlayedByFilledPolygonWithPattern() { string path = this.CreateOutputDirectory("Drawing", "FilledPolygons"); SixLabors.Primitives.PointF[] simplePath = new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; using (Image <Rgba32> image = new Image <Rgba32>(500, 500)) { image .FillPolygon(Brushes.Horizontal(Rgba32.HotPink), simplePath, new GraphicsOptions(true)) .Save($"{path}/Pattern.png"); using (PixelAccessor <Rgba32> sourcePixels = image.Lock()) { Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); } } }
public void DrawTriangle(PointF a, PointF b, PointF c, string color, int penWidth, bool isFill) { var a1 = ToPointF(a, world); var b1 = ToPointF(b, world); var c1 = ToPointF(c, world); var points = new SixLabors.Primitives.PointF[] { a1, b1, c1, a1 }; if (isFill) { commandQueue.Enqueue(ctx => { ctx.FillPolygon(Rgba32.FromHex(color), points, currentOption); }); } else { commandQueue.Enqueue(ctx => { ctx.DrawPolygon(Rgba32.FromHex(color), penWidth, points, currentOption); }); } }
private unsafe Texture CreateTexture(TextKey key) { var size = key.Size; var actualFont = key.Font; var image = _textImagePool.Acquire(new ImageKey { Width = (int)Math.Ceiling(size.X), Height = (int)Math.Ceiling(size.Y) }); // Clear image to transparent. // TODO: Don't need to do this for a newly created image. fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer()) { Unsafe.InitBlock(pin, 0, (uint)(image.Width * image.Height * 4)); } image.Mutate(x => { var location = new SixLabors.Primitives.PointF(0, size.Y / 2.0f); // TODO: Vertical centering is not working properly. location.Y *= 0.8f; var color = key.Color; x.DrawText( new TextGraphicsOptions { WrapTextWidth = size.X, HorizontalAlignment = key.Alignment == TextAlignment.Center ? HorizontalAlignment.Center : HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }, key.Text, actualFont, new Bgra32( (byte)(color.R * 255.0f), (byte)(color.G * 255.0f), (byte)(color.B * 255.0f), (byte)(color.A * 255.0f)), location); }); Texture texture; // Draw image to texture. fixed(void *pin = &image.DangerousGetPinnableReferenceToPixelBuffer()) { texture = _graphicsDevice.ResourceFactory.CreateTexture( TextureDescription.Texture2D( (uint)image.Width, (uint)image.Height, 1, 1, PixelFormat.B8_G8_R8_A8_UNorm, TextureUsage.Sampled)); _graphicsDevice.UpdateTexture( texture, new IntPtr(pin), (uint)(image.Width * image.Height * 4), 0, 0, 0, texture.Width, texture.Height, 1, 0, 0); } _textImagePool.ReleaseAll(); return(texture); }
public static void GenerateAll(List <GqlResponse_Data_Subreddit_Layers_Edge> edges) { //Create the source image and fill it with white Image <Rgba32> image = new Image <Rgba32>(1920, 1080 + 100); for (int x = 0; x < image.Width; x++) { for (int y = 0; y < image.Height; y++) { image[x, y] = new Rgba32(1f, 1f, 1f, 1f); } } //Load font FontCollection fonts = new FontCollection(); FontFamily fontFam = fonts.Install("RobotoMono-Regular.ttf"); var mainFont = fontFam.CreateFont(40); var mainFontRendererOptions = new RendererOptions(mainFont); var smallFont = fontFam.CreateFont(20); var smallFontRendererOptions = new RendererOptions(smallFont); //Start generation int saved = 0; int i = 0; Console.WriteLine("[Canvas] Starting generation..."); List <Task> tasks = new List <Task>(); foreach (var e in edges) { i++; //Skip if this edge does not have an image if (!File.Exists(Program.OUTPUT_IMGS + e.node.id + ".png")) { continue; } //Add this edge to the image. First, open it try { using (FileStream fs = new FileStream(Program.OUTPUT_IMGS + e.node.id + ".png", FileMode.Open)) using (Image <Rgba32> edgeImg = Image.Load <Rgba32>(fs)) { //Resize the image int sizeX = e.node.box.endPoint.x - e.node.box.startPoint.x; int sizeY = e.node.box.endPoint.y - e.node.box.startPoint.y; //edgeImg.Mutate(x => x.Resize(sizeX, sizeY)); edgeImg.Mutate(x => x.Resize(100, 100)); //Copy the image for (int x = 0; x < edgeImg.Width; x++) { for (int y = 0; y < edgeImg.Height; y++) { //Mix color Rgba32 sourcePixel = image[x + e.node.box.startPoint.x, y + e.node.box.startPoint.y]; Rgba32 edgePixel = edgeImg[x, y]; float edgeMult = ((float)edgePixel.A) / 255; float sourceMult = 1 - edgeMult; Rgba32 mixedColor = new Rgba32( ((((float)edgePixel.R) / 255) * edgeMult) + ((((float)sourcePixel.R) / 255) * sourceMult), ((((float)edgePixel.G) / 255) * edgeMult) + ((((float)sourcePixel.G) / 255) * sourceMult), ((((float)edgePixel.B) / 255) * edgeMult) + ((((float)sourcePixel.B) / 255) * sourceMult), ((((float)edgePixel.A) / 255) * edgeMult) + ((((float)sourcePixel.A) / 255) * sourceMult) ); image[x + e.node.box.startPoint.x, y + e.node.box.startPoint.y] = mixedColor; } } } } catch (UnknownImageFormatException err) { //Move image to the corrupted folder File.Move(Program.OUTPUT_IMGS + e.node.id + ".png", Program.OUTPUT_IMGS_CORRUPT + e.node.id + ".png"); } catch (Exception ex) { //Different error. Console.Write("\r[Canvas] Failed to process image " + e.node.id + "! " + ex.Message + ex.StackTrace + "\n"); } //Save every 6th image if (i % 8 == 0) { //Clear bottom for (int x = 0; x < image.Width; x++) { for (int y = 1080; y < 1080 + 100; y++) { image[x, y] = new Rgba32(0f, 0f, 0f, 1f); } } //Load JSON data to get the date var postData = JsonConvert.DeserializeObject <JArray>(File.ReadAllText(Program.OUTPUT_POSTS + e.node.id + ".json")); double unixPostTime = (long)postData[0].SelectToken("data").SelectToken("children")[0].SelectToken("data").SelectToken("created_utc"); DateTime postTime = new DateTime(1970, 1, 1, 0, 0, 0).AddHours(-6).AddSeconds(unixPostTime); //Create date string string date = $"{postTime.DayOfWeek.ToString()} {postTime.Month}/{postTime.Day}/{postTime.Year} {postTime.ToShortTimeString()} CST"; //Set date on the bottom var textSize = TextMeasurer.Measure(date, mainFontRendererOptions); float xTextPos = 50 - (textSize.Height / 2); var pos = new SixLabors.Primitives.PointF(xTextPos, 1080 + 50 - (textSize.Height / 2)); image.Mutate(x => x.DrawText(date, mainFont, Rgba32.White, pos)); //Add credit on side textSize = TextMeasurer.Measure(SIDE_TEXT, smallFontRendererOptions); xTextPos = 1920 - xTextPos - textSize.Width; pos = new SixLabors.Primitives.PointF(xTextPos, 1080 + 50 - (textSize.Height / 2)); image.Mutate(x => x.DrawText(SIDE_TEXT, smallFont, Rgba32.Gray, pos)); //Save tasks.Add(SaveAsync(image.Clone(), Program.OUTPUT_CANVAS + saved++.ToString() + ".png")); } Console.Write($"\r[Canvas] Saved {i}/{edges.Count}... "); } //Wait for all tasks to finish Console.Write("\r[Canvas] Waiting for tasks to finish..."); Task.WaitAll(tasks.ToArray()); //Save last image SaveAsync(image.Clone(), Program.OUTPUT_CANVAS + saved++.ToString() + ".png").GetAwaiter().GetResult(); }