Click here to Skip to main content
15,881,380 members
Articles / Mobile Apps / Windows Phone 7
Tip/Trick

WP7 FloodFill in Texture2D using Scan line Stack Algo

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
5 Feb 2012CPOL 27K   2
WP7 FloodFill in Texture2D using Scan line Stack Algo
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
C#
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>();
        }

        /// <summary>
        /// perform flood fill algorithm and return the updated buffer
        /// </summary>
        /// <param name="screenBuffer"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        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);
        }
        /// <summary>
        /// implements the flood fill scan line stack method to fill the color inside colosed boundry
        /// </summary>
        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:
C#
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.

C#
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...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Pakistan Pakistan
Expertise on Enterprise solutions, Mobile Apps & Services based applications on .NET platform. As Sr. Software Engineer, I have worked on variety of technologies like ASP.NET MVC, MS Windows Phone 7, WCF, and MS SharePoint 2010, MS Dynamics CRM.

Comments and Discussions

 
GeneralActually this algo flood fill the bitmap in this manner. htt... Pin
saboor awan13-Feb-12 7:04
saboor awan13-Feb-12 7:04 
GeneralWhy do you use these spanLeft and spanRight flags ? Pin
YvesDaoust6-Feb-12 20:56
YvesDaoust6-Feb-12 20:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.