2
\$\begingroup\$

I am working on a simple drawing game and I need to get a Flood Fill algorithm working for a Paint Bucket tool.

I have the game running on WinForms at the moment which is extremely slow, but I have a working Flood Fill algorithm there, I could get the code to support SharpDX if I could get the color of a pixel (either from a SharpDX.Direct2D1.Bitmap or from a SharpDX.Direct2D1.RenderTarget), but I can't find a way to do so.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

Since the algorithm I am using accepts System.Drawing.Bitmap I only needed a way to capture a rendered frame onto one and then render the result, this is far from efficient but I've got a solution.

The solution uses PrintWindow from the WIN API.

[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);

This would probably only work if an embedded SharpDX control is used as capturing the control via handle won't do, but capturing a parent control, in this case the form, will return the desired image.

System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

Graphics g = Graphics.FromImage(bmp);
IntPtr hdcBitmap = g.GetHdc();

PrintWindow(Handle, hdcBitmap, 0);

g.ReleaseHdc(hdcBitmap);
g.Dispose();

// Crop the image to return only the part that we need, without control borders.
bmp.Clone(new Rectangle(SharpDXControl.Location.X + 1, SharpDXControl.Location.Y + 1, SharpDXControl.Width - 2, SharpDXControl.Height - 2), bmp.PixelFormat);

To draw the image, I created a new SharpDX.Direct2D1.Bitmap instance and used the pixel data (bits) from the System.Drawing.Bitmap instance.

SharpDX.Direct2D1.Bitmap dxbmp = new SharpDX.Direct2D1.Bitmap(renderTarget, new SharpDX.Size2(bmpWidth, bmpHeight), new BitmapProperties(renderTarget.PixelFormat));
dxbmp.CopyFromMemory(bmpBits, bmpWidth * 4);
renderTarget.DrawBitmap(dxbmp, 1F, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);
dxbmp.Dispose();

The algorithm I am using is a slightly modified version of the Queue-Linear Flood Fill Algorithm.

\$\endgroup\$
0
\$\begingroup\$

In case someone wishes to access pixel data in Direct2D...

Pixel data from a Direct2D1.Bitmap1 is available to access colors.

The Bitmap1 whose pixel data we wish to examine must be created using the Direct2D1.BitmapOptions.CannotDraw AND Direct2D1.BitmapOptions.CpuRead flags in the Direct2D1.BitmapProperties1, which is passed to the Bitmap1 constructor.

The Direct2D documentation fails to mention that both flags are required.

The Map method of Direct2D1.Bitmap1 returns a Direct2D1.DataRectangle. This features two members: DataPointer and Pitch:

DataPointer is an IntPtr which points to the start of the memory occupied by the Bitmap1 we're working on. Under GDI this is referred to as Scan0.

Pitch is the width of the Bitmap1 expressed in bytes but includes padding (a 245x245 image yields a Pitch of 1024, suggesting byte alignment padding).

Here's some code which demonstrates the copying of data to and from a Bitmap1 using Marshal.Copy:

' Create array of bytes for pixel data
m_Bytes = New Byte(m_Bitmap.PixelSize.Width * m_Bitmap.PixelSize.Height * 4 - 1) {}
' Lock the bitmap
m_DataRectangle = m_Bitmap.Map(MapOptions.Read)
' Copy pixel data to array
Marshal.Copy(m_DataRectangle.DataPointer, m_Bytes, 0, m_Bytes.Length)
' Copy pixel data array back to DataRectangle
Marshal.Copy(m_Bytes, 0, m_DataRectangle.DataPointer, m_Bytes.Length)
' Unlock bitmap
m_Bitmap.Unmap()
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .