If you are in WP7 XNA, might be somewhere you need to
FloodFill
in a
texture2D
.
I have a simple class that flood fills in
texture2D
.
This class is using
FloodFill
Scan line Stack algo. it fills the object in this
manner
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
public class FloodFill
{
Stack<Microsoft.Xna.Framework.Point> StkColoringPoints;
public FloodFill()
{
StkColoringPoints = new Stack<Microsoft.Xna.Framework.Point>();
}
public Microsoft.Xna.Framework.Color[,] FloodFillToPoint(Microsoft.Xna.Framework.Color[,] screenBuffer, Vector2 point,Color newColor)
{
StkColoringPoints = new Stack<Microsoft.Xna.Framework.Point>();
Microsoft.Xna.Framework.Point floodInvokePoint = new Microsoft.Xna.Framework.Point((int)point.X, (int)point.Y);
return floodFillScanlineStack(screenBuffer, floodInvokePoint,newColor.PackedValue);
}
private Microsoft.Xna.Framework.Color[,] floodFillScanlineStack(Microsoft.Xna.Framework.Color[,] screenBuffer, Microsoft.Xna.Framework.Point floodInvokePoint, uint newColorCode)
{
uint oldColorCode = screenBuffer[floodInvokePoint.X, floodInvokePoint.Y].PackedValue;
if (oldColorCode == newColorCode)
return screenBuffer;
int y1;
bool spanLeft, spanRight;
int BUFFERWIDTH = screenBuffer.GetLength(0);
int BUFFERHEIGHT = screenBuffer.GetLength(1);
StkColoringPoints.Push(floodInvokePoint);
while (StkColoringPoints.Count > 0)
{
floodInvokePoint = StkColoringPoints.Pop();
y1 = floodInvokePoint.Y;
while (y1 >= 0 && screenBuffer[floodInvokePoint.X, y1].PackedValue == oldColorCode) y1--;
y1++;
spanLeft = spanRight = false;
while (y1 < BUFFERHEIGHT && screenBuffer[floodInvokePoint.X, y1].PackedValue == oldColorCode)
{
screenBuffer[floodInvokePoint.X, y1].PackedValue = newColorCode;
if (!spanLeft && floodInvokePoint.X > 0 && screenBuffer[floodInvokePoint.X - 1, y1].PackedValue == oldColorCode)
{
StkColoringPoints.Push(new Microsoft.Xna.Framework.Point { X = floodInvokePoint.X - 1, Y = y1 });
spanLeft = true;
}
else if (spanLeft && floodInvokePoint.X > 0 && screenBuffer[floodInvokePoint.X - 1, y1].PackedValue != oldColorCode)
{
spanLeft = false;
}
if (!spanRight && floodInvokePoint.X < BUFFERWIDTH - 1 && screenBuffer[floodInvokePoint.X + 1, y1].PackedValue == oldColorCode)
{
StkColoringPoints.Push(new Microsoft.Xna.Framework.Point { X = floodInvokePoint.X + 1, Y = y1 });
spanRight = true;
}
else if (spanRight && floodInvokePoint.X < BUFFERWIDTH - 1 && screenBuffer[floodInvokePoint.X + 1, y1].PackedValue != oldColorCode)
{
spanRight = false;
}
y1++;
}
}
return screenBuffer;
}
}
Some utility functions:
private Microsoft.Xna.Framework.Color[,] ConvertTo2DArray(Microsoft.Xna.Framework.Color[] data, int columns, int rows)
{
Microsoft.Xna.Framework.Color[,] data2d = new Microsoft.Xna.Framework.Color[columns, rows];
int counter = 0;
for (int h = 0; h < rows; h++)
{
for (int w = 0; w < columns; w++)
data2d[w, h] = data[counter++];
}
return data2d;
}
private Microsoft.Xna.Framework.Color[] ConvertTo1DArray(Microsoft.Xna.Framework.Color[,] data2d)
{
Microsoft.Xna.Framework.Color[] data = new Microsoft.Xna.Framework.Color[data2d.Length];
int counter = 0;
for (int h = 0; h < data2d.GetLength(1); h++)
{
for (int w = 0; w < data2d.GetLength(0); w++)
data[counter++] = data2d[w, h];
}
return data;
}
Assuming
ColoringObject.Texture
is your texture.
Microsoft.Xna.Framework.Color[] Texture1D = new Microsoft.Xna.Framework.Color [ ColoringObject.Texture.Width * ColoringObject.Texture.Height];
ColoringObject.Texture.GetData(Texture1D);
FloodFill floodfill = new FloodFill();
Microsoft.Xna.Framework.Color[,] Texture2D = ConvertTo2DArray(Texture1D, ColoringObject.Texture.Width, ColoringObject.Texture.Height);
Texture2D = floodfill.FloodFillToPoint(Texture2D,touchPosition,this.fillingColor);
Texture1D = ConvertTo1DArray(Texture2D);
this.SpriteBatch.GraphicsDevice.Textures[0] = null;
ColoringObject.Texture.SetData(Texture1D);
Happy coding...