/// <summary> /// Obtain a gdi+ System.Drawing.Bitmap from <see cref="RenderingBuffer"/> /// </summary> public static System.Drawing.Bitmap GetBitmap(PixelsBuffer source, PixelFormat format) { System.Drawing.Bitmap bmp = null; int width = source.Width; int height = source.Height; Rectangle r = new Rectangle(0, 0, width, height); bmp = new System.Drawing.Bitmap(width, height, format); BitmapData data = bmp.LockBits(r, ImageLockMode.ReadWrite, format); IntPtr ptr = data.Scan0; //calculate buffer size int size = 0; int bpp = 0; switch (format) { case PixelFormat.Format24bppRgb: bpp = 24; break; case PixelFormat.Format32bppArgb: bpp = 32; break; case PixelFormat.Format32bppPArgb: bpp = 32; break; case PixelFormat.Format32bppRgb: bpp = 32; break; case PixelFormat.Format48bppRgb: bpp = 48; break; case PixelFormat.Format4bppIndexed: bpp = 48; break; case PixelFormat.Format64bppArgb: bpp = 64; break; case PixelFormat.Format64bppPArgb: bpp = 64; break; case PixelFormat.Format8bppIndexed: bpp = 8; break; } size = width * (bpp / 8) * height; //byte[] buffer = new byte[size]; //System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, size); //copy from source to buffer byte[] buffer = source.ToBytes(PixelFormats.Bgra); //source.Buffer.CopyTo(buffer, 0); //copy back to System.Drawing.Bitmap System.Runtime.InteropServices.Marshal.Copy(buffer, 0, ptr, size); bmp.UnlockBits(data); return bmp; }
/// <summary> /// Create a new instance and copy the content of this buffer to the new one /// </summary> public PixelsBuffer Clone() { PixelsBuffer result = new PixelsBuffer(Width, Height, Stride); Array.Copy(Data, result.Data, Data.Length); return(result); }
/// <summary> /// Create a new instance with exact width, height, stride as source. Then copy the data of source to new instance /// </summary> public PixelsBuffer(PixelsBuffer source) { Width = source.Width; Height = source.Height; Stride = source.Stride; Data = new uint[source.Data.Length]; Array.Copy(source.Data, Data, source.Data.Length); }
/// <summary> /// Create a new buffer that attaches to this buffer as a sub-view. /// </summary> /// <param name="left">Horizontal (column) offset</param> /// <param name="top">Vertical (row) offset</param> /// <param name="width">New view's horizontal width</param> /// <param name="height">New view's vertical height</param> /// <param name="inversed">When true, the y-axis is reversed</param> public PixelsBuffer CreateView(int left, int top, int width, int height, bool inversed = false) { PixelsBuffer result = new PixelsBuffer(); int stride = this.Stride; if (inversed) stride = -stride; int offset = StartOffset + top * stride + left;// this.GetPixelIndex(left, top); result.Attach(this.Data, width, height, stride, offset); return result; }
private void fmFill_Load(object sender, EventArgs e) { if (!DesignMode) { buffer = new PixelsBuffer(w, h); drawer = new Drawer(buffer); Draw(); } }
/// <summary> /// Copy the content of this buffer to target buffer. /// <para>The target's width, height, stride must be the same as this one</para> /// </summary> public void CopyTo(PixelsBuffer target) { if (target.Data.Length == Data.Length) { Array.Copy(Data, target.Data, Data.Length); } else { throw new Exception("Target must have exact width, height and stride as this"); } }
/// <summary> /// Obtain a Bitmap from <see cref="RenderingBuffer"/> /// </summary> public static Bitmap GetBitmap(PixelsBuffer source, Bitmap.Config config = null) { var bmp = Bitmap.CreateBitmap(Array.ConvertAll<uint, int>(source.Data, new Converter<uint, int>(x => (int)x)), source.StartOffset, source.Stride, source.Width, source.Height, Bitmap.Config.Argb8888); if (config != null && !config.Equals(Bitmap.Config.Argb8888)) { var tmp = ConvertConfig(bmp, config); bmp.Dispose(); bmp = tmp; } return bmp; }
/// <summary> /// Create a new buffer that attaches to this buffer as a sub-view. /// </summary> /// <param name="left">Horizontal (column) offset</param> /// <param name="top">Vertical (row) offset</param> /// <param name="width">New view's horizontal width</param> /// <param name="height">New view's vertical height</param> /// <param name="inversed">When true, the y-axis is reversed</param> public PixelsBuffer CreateView(int left, int top, int width, int height, bool inversed = false) { PixelsBuffer result = new PixelsBuffer(); int stride = this.Stride; if (inversed) { stride = -stride; } int offset = StartOffset + top * stride + left;// this.GetPixelIndex(left, top); result.Attach(this.Data, width, height, stride, offset); return(result); }
private void Draw(ImageView imageView, int times) { var start = DateTime.Now; PixelsBuffer buffer = new PixelsBuffer(600, 600); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.Transparent); //create fill for drawing Fill fill = new Fill(Colors.Transparent); //fill.Opacity = 0.3; //draw content var coords1 = GetPath(1); var coords2 = GetPath(0); var coords3 = GetPath(2); var path = GetPath(); var startDraw = DateTime.Now; int step = 5; for (int i = 0; i < times; i++) { //drawer.DrawRectangle(fill, 10, 10, 300, 300); //drawer.DrawEllipse(fill, 200, 200, 120, 200); //drawer.DrawPolygon(fill, coords1); //drawer.DrawPolygon(fill, coords2); //drawer.DrawPolygon(fill, coords3); //draw content //drawer.Rotate(15); //drawer.Scale(0.3, 0.3); //drawer.DrawPath(fill, path); var margin = i / 10 * step; PixelsBuffer view = buffer.CreateView(margin, margin, buffer.Width - margin * 2, buffer.Height - margin * 2, true); DrawFrame(view, Colors.OrangeRed); DrawLine(view, Colors.Olive); } DrawLion(buffer, 200, 200); if (bmp != null) bmp.Dispose(); bmp = BufferToBitmap.GetBitmap(buffer); //show to screen var icon = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.Icon); imageView.SetImageBitmap(BufferToBitmap.Overlay(new Bitmap[] { icon, bmp })); Android.Util.Log.Debug("Draw " + times, "Draw: " + (DateTime.Now - startDraw).TotalSeconds.ToString() + " Total: " + (DateTime.Now - start).TotalSeconds.ToString()); }
public static void DrawBitmapToBuffer(Bitmap source, PixelsBuffer buffer) { //make sure we have a ABGR Bitmap, same as PixelFormat.Format32bppArgb var bmp = ConvertConfig(source, Bitmap.Config.Argb8888); //copy Bitmap's data to buffer IntPtr ptr = bmp.LockPixels(); int size = bmp.RowBytes * bmp.Height; byte[] tmpBuffer = new byte[bmp.Width * bmp.Height * 4]; System.Runtime.InteropServices.Marshal.Copy(ptr, tmpBuffer, 0, size); bmp.UnlockPixels(); //copy to pixel buffer buffer.FromBytes(tmpBuffer, PixelFormats.Bgra); }
private void btnDrawEllipse_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.Yellow; //draw content drawer.DrawEllipse(fill, 200, 200, 180, 100); //show to screen DisplayBuffer(buffer); }
private void btnDrawRoundRect_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.DarkOrange; //draw content drawer.DrawRoundedRectangle(fill, 50, 50, 300, 200, 15, 15); //show to screen DisplayBuffer(buffer); }
private void btnDrawPixels_Click(object sender, EventArgs e) { //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //render to buffer DrawLine(buffer, Colors.Red); DrawFrame(buffer, Colors.Red); //show to screen DisplayBuffer(buffer); #region Description string msg = "Create new buffer, then manually set pixels to buffer to render a rectangular frame around the buffer and a diagonal line from point (0,0) to point (width, height)"; txtDescription.Text = msg; #endregion }
private void btnBufferInBuffer_Click(object sender, EventArgs e) { //create main buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //create a sub view (100 pixels margin) int margin = 100; #region Approach 1 //calculate new view's parameter by hand //then attach the new view to main buffer /* int viewStride = -buffer.Stride; //inverse coordinate system of view int viewOffset = buffer.GetPixelIndex(margin, margin); PixelBuffer view = new PixelBuffer(); view.Attach(buffer, width - margin * 2, height - margin * 2, viewStride, viewOffset); */ #endregion #region Approach 2 //a much easier way to create sub-view PixelsBuffer view = buffer.CreateView(margin, margin, width - margin * 2, height - margin * 2, true); #endregion //render to main buffer DrawLine(buffer, Colors.Red); DrawFrame(buffer, Colors.Red); //render to sub view DrawLine(view, Colors.Blue); DrawFrame(view, Colors.Blue); //show to screen DisplayBuffer(buffer); #region Description string msg = "This example creates a main buffer, render pixels to it. Then, create a sub-view with inversed y-axis, and render to this view."; txtDescription.Text = msg; #endregion }
/// <summary> /// Draw a gdi+ System.Drawing.Bitmap to the rendering buffer /// </summary> public static void DrawBitmapToBuffer(Image source, PixelsBuffer buffer) { //make sure we have a ABGR System.Drawing.Bitmap Bitmap bmp = null; bmp = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp); g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height)); g.Dispose(); //copy System.Drawing.Bitmap's data to buffer Rectangle r = new Rectangle(0, 0, source.Width, source.Height); BitmapData data = bmp.LockBits(r, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); IntPtr ptr = data.Scan0; int size = data.Stride * bmp.Height; byte[] tmpBuffer = new byte[bmp.Width * bmp.Height * 4]; System.Runtime.InteropServices.Marshal.Copy(ptr, tmpBuffer, 0, size); bmp.UnlockBits(data); //copy to pixel buffer buffer.FromBytes(tmpBuffer, PixelFormats.Bgra); }
private void btnInverseDraw_Click(object sender, EventArgs e) { //intentionally make the stride negative so that //the coordinate system is flipped from top-down to bottom-up int stride = -height; //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height, stride); //render to buffer DrawLine(buffer, Colors.Blue); DrawFrame(buffer, Colors.Blue); //show to screen DisplayBuffer(buffer); #region Description string msg = "Exactly similar to Draw Pixel, except that the y-axis coordinate system is inversed (top-down -> bottom-up)"; txtDescription.Text = msg; #endregion }
private void btnDrawStar_Click(object sender, EventArgs e) { //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //render DrawStar(buffer, Colors.Red, Colors.White); //show to screen DisplayBuffer(buffer); #region Description string msg = "Create new buffer, then draw a star"; txtDescription.Text = msg; #endregion }
/// <summary> /// Draw a diagonal line with the specified color from (0,0) to (width, height) /// </summary> void DrawLine(PixelsBuffer buffer, Color color) { int idx = 0; //pixel index for (int i = 0; i < buffer.Height; i++) { idx = buffer.StartOffset + i * buffer.Stride + i; // buffer.GetPixelIndex(i, i); buffer.Data[idx] = color.Data; } }
/// <summary> /// Draw a frame around the buffer from (0,0) to (width, height) /// </summary> void DrawFrame(PixelsBuffer buffer, Color color) { int idx = 0; //pixel index //draw left, right lines for (int y = 0; y < buffer.Height; y++) { //left idx = buffer.StartOffset + buffer.Stride * y;// buffer.GetPixelIndex(0, y); buffer.Data[idx] = color.Data; //right idx = buffer.StartOffset + buffer.Stride * y + buffer.Width - 1;// buffer.GetPixelIndex(buffer.Width - 1, y); buffer.Data[idx] = color.Data; } //draw top, bottom lines for (int x = 0; x < buffer.Width; x++) { //top idx = buffer.StartOffset + x;// buffer.GetPixelIndex(x, 0); buffer.Data[idx] = color.Data; //bottom idx = buffer.StartOffset + (buffer.Height - 1) * buffer.Stride + x;// buffer.GetPixelIndex(x, buffer.Height - 1); buffer.Data[idx] = color.Data; } }
/// <summary> /// Setup this buffer by using an existing pixel buffer /// </summary> /// <param name="buffer">The memory buffer space to attach to</param> /// <param name="width">Horizontal size of buffer (in pixels)</param> /// <param name="height">Vertical size of buffer (in pixels)</param> /// <param name="stride">The number of bytes a row contains</param> /// <param name="startOffset">Index of the starting pixel</param> public void Attach(PixelsBuffer buffer, int width, int height, int stride, int startOffset) { Attach(buffer.Data, width, height, stride, startOffset); }
private void btnDrawPath_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.MistyRose; //create path DrawingPath path = new DrawingPath(); path.MoveTo(200, 100); path.CurveTo(200, 350, 340, 30, 360, 200); path.CurveTo(200, 100, 40, 200, 60, 30); //draw content drawer.Rotate(15); drawer.Scale(0.3, 0.3); drawer.DrawPath(fill, path); //show to screen DisplayBuffer(buffer); }
/// <summary> /// Obtains a rendering buffer from a gdi+ System.Drawing.Bitmap /// </summary> public static PixelsBuffer GetBuffer(Image source) { PixelsBuffer result = new PixelsBuffer(source.Width, source.Height, source.Width); DrawBitmapToBuffer(source, result); return result; }
private void btnDrawTest_Click(object sender, EventArgs e) { if (lstTests.SelectedIndex < 0) lstTests.SelectedIndex = 0; //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(600, 600); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.Black; //populate polygon coordinate data double[] coordinates = null; switch (lstTests.SelectedIndex) { case 0: coordinates = TestFactory.Triangle(); TestFactory.Scale(coordinates, 5.0); break; case 1: coordinates = TestFactory.Star(); TestFactory.Scale(coordinates, 5.0); break; case 2: coordinates = TestFactory.Crown(); TestFactory.Scale(coordinates, 5.0); break; case 3: coordinates = TestFactory.CirclePattern1(buffer.Width, buffer.Height); break; case 4: coordinates = TestFactory.CirclePattern2(buffer.Width, buffer.Height); break; case 5: coordinates = TestFactory.Complex1(); break; case 6: coordinates = TestFactory.Complex2(); break; case 7: coordinates = TestFactory.Complex3(); break; case 8: DrawLion(); break; } if (coordinates != null) { //draw content drawer.DrawPolygon(fill, coordinates); //show to screen DisplayBuffer(buffer); } }
private void btnBufferInBufferDraw_Click(object sender, EventArgs e) { //create & render to main buffer PixelsBuffer buffer = new PixelsBuffer(width, height); DrawStar(buffer, Colors.Red, Colors.White); //create a sub view (50, 50, 100, 100) - inversed PixelsBuffer view = buffer.CreateView(50, 250, 100, 100, true); DrawStar(view, Colors.Blue, Colors.YellowGreen); //create a sub view (50, 50, 100, 100) view = buffer.CreateView(250, 150, 100, 100); DrawStar(view, Colors.Goldenrod, Colors.LemonChiffon); //show to screen DisplayBuffer(buffer); #region Description string msg = "This example demonstrates that logical views with different coordinate systems can be attached to the same pixel buffer"; txtDescription.Text = msg; #endregion }
private void fmGammaCorrection_Load(object sender, EventArgs e) { buffer = new PixelsBuffer(400, 400); drawer = new Drawer(buffer); DrawLion(); }
/// <summary> /// Helper method to display result from a pixel buffer /// </summary> void DisplayBuffer(PixelsBuffer buffer) { if (bmp != null) bmp.Dispose(); bmp = Cross.Helpers.BufferToBitmap.GetBitmap(buffer, System.Drawing.Imaging.PixelFormat.Format32bppArgb); pbView.Image = bmp; }
void DrawLion() { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //get coordinates and colors double[][] polygons = LionPathHelper.GetLionPolygons(); Color[] colors = LionPathHelper.GetLionColors(); //iterate all polygons and draw them double[] coordinates = null; for (int i = 0; i < polygons.Length; i++) { coordinates = polygons[i]; Fill fill = new Fill(colors[i]); drawer.DrawPolygon(fill, coordinates); } //show to screen DisplayBuffer(buffer); }
/// <summary> /// Render a star shape to buffer /// </summary> void DrawStar(PixelsBuffer buffer, Color color, Color background) { IDrawer drawer = new Drawer(buffer); drawer.Clear(background); Fill fill = new Fill(color); double[] coordinates = TestFactory.Star(); TestFactory.Scale(coordinates, 2.0); //drawer.DrawRectangle(stroke, 0, 0, buffer.Width, buffer.Height); drawer.DrawPolygon(fill, coordinates); }
/// <summary> /// Copy the content of this buffer to target buffer. /// <para>The target's width, height, stride must be the same as this one</para> /// </summary> public void CopyTo(PixelsBuffer target) { if (target.Data.Length == Data.Length) Array.Copy(Data, target.Data, Data.Length); else throw new Exception("Target must have exact width, height and stride as this"); }
/// <summary> /// Create a new instance and copy the content of this buffer to the new one /// </summary> public PixelsBuffer Clone() { PixelsBuffer result = new PixelsBuffer(Width, Height, Stride); Array.Copy(Data, result.Data, Data.Length); return result; }
private void btnDrawPolygon_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.MistyRose; //populate polygon coordinate data double[] coordinates = new double[] { 30, 300, 150, 40, 300, 260, 130, 200, //30, 300 //the last point is omitted to show that the end point is important //for rendering stroke }; //draw content drawer.DrawPolygon(fill, coordinates); //show to screen DisplayBuffer(buffer); }
void DrawLion(PixelsBuffer buffer, int x, int y) { //create a new drawing context //PixelBuffer buffer = new PixelBuffer(400, 400); IDrawer drawer = new Drawer(buffer); //get coordinates and colors double[][] polygons = LionPathHelper.GetLionPolygons(); Cross.Drawing.Color[] colors = LionPathHelper.GetLionColors(); //iterate all polygons and draw them double[] coordinates = null; drawer.Translate(x, y); for (int i = 0; i < polygons.Length; i++) { coordinates = polygons[i]; Fill fill = new Fill(colors[i]); drawer.DrawPolygon(fill, coordinates); } }
/// <summary> /// Create a new instance for the provided buffer /// </summary> public Drawer(PixelsBuffer buffer) { Buffer = buffer; }