Skip to content

Commit

Permalink
Added flood fill
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes85 committed Jul 16, 2014
1 parent 9f0b279 commit a4cc89b
Show file tree
Hide file tree
Showing 10 changed files with 458 additions and 222 deletions.
79 changes: 79 additions & 0 deletions MagicPaint/FastBitmap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;

namespace MagicPaint
{
// Thanks to: http://www.vcskicks.com/fast-image-processing2.php
unsafe public class FastBitmap
{
private struct PixelData
{
public byte blue;
public byte green;
public byte red;
public byte alpha;

public override string ToString()
{
return "(" + alpha.ToString() + ", " + red.ToString() + ", " + green.ToString() + ", " + blue.ToString() + ")";
}
}

private Bitmap workingBitmap = null;
private int width = 0;
private BitmapData bitmapData = null;
private Byte* pBase = null;

public FastBitmap(Bitmap inputBitmap)
{
workingBitmap = inputBitmap;
}

public void LockImage()
{
Rectangle bounds = new Rectangle(Point.Empty, workingBitmap.Size);

width = (int)(bounds.Width * sizeof(PixelData));
if (width % 4 != 0) width = 4 * (width / 4 + 1);

//Lock Image
bitmapData = workingBitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
pBase = (Byte*)bitmapData.Scan0.ToPointer();
}

private PixelData* pixelData = null;

public Color GetPixel(int x, int y)
{
pixelData = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue);
}

public Color GetPixelNext()
{
pixelData++;
return Color.FromArgb(pixelData->alpha, pixelData->red, pixelData->green, pixelData->blue);
}

public void SetPixel(int x, int y, Color color)
{
PixelData* data = (PixelData*)(pBase + y * width + x * sizeof(PixelData));
data->alpha = color.A;
data->red = color.R;
data->green = color.G;
data->blue = color.B;
}

public void UnlockImage()
{
workingBitmap.UnlockBits(bitmapData);
bitmapData = null;
pBase = null;
}
}
}
337 changes: 175 additions & 162 deletions MagicPaint/Form1.Designer.cs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions MagicPaint/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ private void btnToolBrush_Click_1(object sender, EventArgs e)
SetCurrentTool(MagicPixler.Tool.Brush);
}

private void btnToolFill_Click(object sender, EventArgs e)
{
SetCurrentTool(MagicPixler.Tool.Fill);
}

private void pnlCurrentColor_Click(object sender, EventArgs e)
{
colorDialog1.FullOpen = true;
Expand Down Expand Up @@ -344,6 +349,7 @@ private void SetCurrentTool(MagicPixler.Tool tool)
{
btnToolBrush.Enabled = true;
btnToolColorPicker.Enabled = true;
btnToolFill.Enabled = true;
switch (tool)
{
case MagicPixler.Tool.Brush:
Expand All @@ -352,6 +358,9 @@ private void SetCurrentTool(MagicPixler.Tool tool)
case MagicPixler.Tool.ColorPicker:
btnToolColorPicker.Enabled = false;
break;
case MagicPixler.Tool.Fill:
btnToolFill.Enabled = false;
break;
}
magicPixler1.CurrentTool = tool;
}
Expand Down Expand Up @@ -433,5 +442,6 @@ private void SetZoomLevel(int percent)
{
magicPixler1.PixelSize = (int)Math.Round(1.0 / 100.0 * percent, 0);
}

}
}
42 changes: 21 additions & 21 deletions MagicPaint/Form1.resx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
<data name="btnSaveFrame.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vgAADr4B6kKxwAAAAghJREFUOE+t00lvEnEYx/HnXTS1RaCUtam2pXQRK7TWEjWtqVuFqnF9CSS8BcuF
vAAADrwBlbxySQAAAghJREFUOE+t00lvEnEYx/HnXTS1RaCUtam2pXQRK7TWEjWtqVuFqnF9CSS8BcuF
K4lK9cKNiw1L7FtASBAOtnowsbhRys6w+PP/jJMUEi81TvLJf2byfCeTzH/ovxwul6u4fHEZb3YSfXai
7C2i8V3EEruICwmBZ7lRcqIl5yI8bjdK1RaOevB1udZCpd5GrdlBQ+pAanfx9PETcKPkRM4LDjx68BBS
q4vn0VSfFyyWwstYGqF4Gt3uL3mWGyUnWji/gPt376Hd6aIptSEJvLJGs4Vao4VqXUK52kRZrDzLjZIT
Expand All @@ -208,26 +208,6 @@
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>488, 17</value>
</metadata>
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN
0gAADdIBb5L+jgAAAAd0SU1FB9sDFgEMFDFSxZkAAAM/SURBVDhPfZNrSFNxGMZPQhBB0AXKT9WXKCsI
CiMoAg38UhQKgWWFmbqZ1WYaYZGWaWqallOPmylelst7mywvc15nXrbZdE4n081ddFN33LxsO0eXbztu
RSPqB4eH/3ve5z0P55wXobABKOxNQFxgZnOAwaDnN3D5C+VVtTZ+c+uEVDLwQTEs2kneJyF7SY/niCD7
4jZh230AsM9VFLO5UM3rxDSmNVjGAWsfmgZGGc9UUMKBz/WNF58xB2BHHMDeJ38MIBF+G4UcVi02Z3XO
68yEXr9ETOvMuEq9SCgnjbhKMGSYzkM/br4vrjnmsSDbYzwzRuXyQ7U8ASHXrmmVc/bxqXlcosYIkQYj
hKpFQiCfdXRINTbx+6p+xbC4rzMO/e799BGZ+E12RS8MqtaGZHq7cNJM1KuX18tmVtaLXJqvxIgSnWX9
2xfJSkfKOxZ++PiZXYJPOR63i94eYXt4ek/L91mHZEhvL1EsEelKK/FMjuGP+o32cJ5u9Tp3ao3WPuVo
ikzMn6Blcb0TfOU3toamiqB6ZLVUubJRo8E3Sl0XqnU4GTrcWaDHnUVa3FneMYNX3k9mqUJCLgd1czI9
bhc11ZWMiIz2tueNpkxUbrlZorQEFg2b/XP6TCffiYwn8iULp0snrZc+yxxZUfQkA+2DyDtBIZp3MoPF
heKuJXbpqJXCmV4JKhvBzhb0Gv2y2wxHmIMLp7pMthvsQVvVnfBbatLj9Q5IZNIBDrt1YjxTgKVVqVdD
KsctFxjdc36vatQHB2ftVwaMkBuflGENuhrsn8CUeScgoTHEkJudKox+USxPabG9rdNsUvowCJMuA/WL
zMKkPU2ypr15raAlptwk+70S/DqEVsDuyJhY2o2w0Knb0XRb5MNE893oWHtYaLDg3DW6n2JMbuNx6+FB
VvPfCeIL+reKUfkq3y1lLewPvJe5m94PuxAAn8i8SV/qA3qAdkYD5eUf8cDzRw88zmkiWxGE6lqO2AZw
PkHdQxKY7j8tAZW6tVC8pfHoMLx8lUpdnJ+FXLSMrPmER9whlwlgT7x7OX59338pydVkMZiMesh4mz7m
Kbn5vRz/YTv1x5bW1dU1dPd06REEQX4CcfkB+/p+LtUAAAAASUVORK5CYII=
</value>
</data>
<data name="palette1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAALsAAACPCAYAAACie6rRAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
Expand Down Expand Up @@ -569,6 +549,26 @@
xG+3ycLvmXtL2D+2xbB+oi2G9RNtMayfaIth/URbBPWbNVn47XNv4VP95F+3/Nzf0ED4DQuY39Dg+g0N
2E+kycL7597CJ/tRY5/0Sf9u56f9Oxtwv5FNFt4795awf2yLIfh3pUUA/v/ZZOFdc+5dk/8X4BnCK30m
xasAAAAASUVORK5CYII=
</value>
</data>
<data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN
0AAADdABEGw9BwAAAAd0SU1FB9sDFgEMFDFSxZkAAAM/SURBVDhPfZNrSFNxGMZPQhBB0AXKT9WXKCsI
CiMoAg38UhQKgWWFmbqZ1WYaYZGWaWqallOPmylelst7mywvc15nXrbZdE4n081ddFN33LxsO0eXbztu
RSPqB4eH/3ve5z0P55wXobABKOxNQFxgZnOAwaDnN3D5C+VVtTZ+c+uEVDLwQTEs2kneJyF7SY/niCD7
4jZh230AsM9VFLO5UM3rxDSmNVjGAWsfmgZGGc9UUMKBz/WNF58xB2BHHMDeJ38MIBF+G4UcVi02Z3XO
68yEXr9ETOvMuEq9SCgnjbhKMGSYzkM/br4vrjnmsSDbYzwzRuXyQ7U8ASHXrmmVc/bxqXlcosYIkQYj
hKpFQiCfdXRINTbx+6p+xbC4rzMO/e799BGZ+E12RS8MqtaGZHq7cNJM1KuX18tmVtaLXJqvxIgSnWX9
2xfJSkfKOxZ++PiZXYJPOR63i94eYXt4ek/L91mHZEhvL1EsEelKK/FMjuGP+o32cJ5u9Tp3ao3WPuVo
ikzMn6Blcb0TfOU3toamiqB6ZLVUubJRo8E3Sl0XqnU4GTrcWaDHnUVa3FneMYNX3k9mqUJCLgd1czI9
bhc11ZWMiIz2tueNpkxUbrlZorQEFg2b/XP6TCffiYwn8iULp0snrZc+yxxZUfQkA+2DyDtBIZp3MoPF
heKuJXbpqJXCmV4JKhvBzhb0Gv2y2wxHmIMLp7pMthvsQVvVnfBbatLj9Q5IZNIBDrt1YjxTgKVVqVdD
KsctFxjdc36vatQHB2ftVwaMkBuflGENuhrsn8CUeScgoTHEkJudKox+USxPabG9rdNsUvowCJMuA/WL
zMKkPU2ypr15raAlptwk+70S/DqEVsDuyJhY2o2w0Knb0XRb5MNE893oWHtYaLDg3DW6n2JMbuNx6+FB
VvPfCeIL+reKUfkq3y1lLewPvJe5m94PuxAAn8i8SV/qA3qAdkYD5eUf8cDzRw88zmkiWxGE6lqO2AZw
PkHdQxKY7j8tAZW6tVC8pfHoMLx8lUpdnJ+FXLSMrPmER9whlwlgT7x7OX59338pydVkMZiMesh4mz7m
Kbn5vRz/YTv1x5bW1dU1dPd06REEQX4CcfkB+/p+LtUAAAAASUVORK5CYII=
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
Expand Down
3 changes: 3 additions & 0 deletions MagicPaint/MagicPaint.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>icon.ico</ApplicationIcon>
Expand All @@ -47,6 +48,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FastBitmap.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
Expand Down Expand Up @@ -180,6 +182,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="icon.ico" />
<None Include="Resources\fill-color.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
45 changes: 44 additions & 1 deletion MagicPaint/MagicPixler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public int PixelSize
public enum Tool
{
Brush = 0,
ColorPicker = 1
ColorPicker = 1,
Fill = 2
}

public MagicPixler()
Expand Down Expand Up @@ -174,9 +175,51 @@ private void UseTool(int x, int y)
OnColorChoose(this, color);
}
}
else if (CurrentTool == Tool.Fill)
{
FloodFill(x, y, image.GetPixel(x, y), CurrentColor);
}
}
}

private void FloodFill(int x, int y, Color oldColor, Color newColor)
{
Stack<Point> floodFillStack = new Stack<Point>();
floodFillStack.Push(new Point(x, y));

while (floodFillStack.Count > 0)
{
Point currentPoint = floodFillStack.Pop();
Color currentColor = image.GetPixel(currentPoint.X, currentPoint.Y);

if (EqualColor(currentColor, oldColor) && !EqualColor(currentColor, newColor))
{
image.SetPixel(currentPoint.X, currentPoint.Y, newColor);
if (currentPoint.X > 0)
{
floodFillStack.Push(new Point(currentPoint.X - 1, currentPoint.Y));
}
if (currentPoint.Y > 0)
{
floodFillStack.Push(new Point(currentPoint.X, currentPoint.Y - 1));
}
if ((currentPoint.X + 1) < image.Width)
{
floodFillStack.Push(new Point(currentPoint.X + 1, currentPoint.Y));
}
if ((currentPoint.Y + 1) < image.Height)
{
floodFillStack.Push(new Point(currentPoint.X, currentPoint.Y + 1));
}
}
}
}

private Boolean EqualColor(Color color1, Color color2)
{
return (color1.ToArgb() == color2.ToArgb());
}

private void MagicPixler_Resize(object sender, EventArgs e)
{
RefreshEditor();
Expand Down
Loading

0 comments on commit a4cc89b

Please sign in to comment.