Exemplo n.º 1
0
        /// <summary>Removes and returns the <see cref="FloodFillRange"/> at the beginning of the queue.</summary>
        public FloodFillRange Dequeue()
        {
            FloodFillRange range = new FloodFillRange();

            if (size > 0)
            {
                range       = array[head];
                array[head] = new FloodFillRange();
                head++; //advance head position
                size--; //update size to exclude dequeued item
            }
            return(range);
        }
Exemplo n.º 2
0
        private void DoFloodFill(Point pt)
        {
            ranges = new FloodFillRangeQueue(((bitmapWidth + bitmapHeight) / 2) * 5);//new Queue<FloodFillRange>();

            //***Get starting color.
            int x = pt.X; int y = pt.Y;
            int idx = CoordsToByteIndex(ref x, ref y);

            startColor = new byte[] { bitmap.Bits[idx], bitmap.Bits[idx + 1], bitmap.Bits[idx + 2] };

            bool[] pixelsChecked = this.pixelsChecked;

            //***Do first call to floodfill.
            LinearFill(ref x, ref y);

            //***Call floodfill routine while floodfill ranges still exist on the queue
            while (ranges.Count > 0)
            {
                //**Get Next Range Off the Queue
                FloodFillRange range = ranges.Dequeue();

                //**Check Above and Below Each Pixel in the Floodfill Range
                int downPxIdx = (bitmapWidth * (range.Y + 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc,y+1);
                int upPxIdx   = (bitmapWidth * (range.Y - 1)) + range.StartX; //CoordsToPixelIndex(lFillLoc, y - 1);
                int upY       = range.Y - 1;                                  //so we can pass the y coord by ref
                int downY     = range.Y + 1;
                int tempIdx;
                for (int i = range.StartX; i <= range.EndX; i++)
                {
                    //*Start Fill Upwards
                    //if we're not above the top of the bitmap and the pixel above this one is within the color tolerance
                    tempIdx = CoordsToByteIndex(ref i, ref upY);
                    if (range.Y > 0 && (!pixelsChecked[upPxIdx]) && CheckPixel(ref tempIdx))
                    {
                        LinearFill(ref i, ref upY);
                    }

                    //*Start Fill Downwards
                    //if we're not below the bottom of the bitmap and the pixel below this one is within the color tolerance
                    tempIdx = CoordsToByteIndex(ref i, ref downY);
                    if (range.Y < (bitmapHeight - 1) && (!pixelsChecked[downPxIdx]) && CheckPixel(ref tempIdx))
                    {
                        LinearFill(ref i, ref downY);
                    }
                    downPxIdx++;
                    upPxIdx++;
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Finds the furthermost left and right boundaries of the fill area
        /// on a given y coordinate, starting from a given x coordinate, filling as it goes.
        /// Adds the resulting horizontal range to the queue of floodfill ranges,
        /// to be processed in the main loop.
        /// </summary>
        /// <param name="x">The x coordinate to start from.</param>
        /// <param name="y">The y coordinate to check at.</param>
        private void LinearFill(ref int x, ref int y)
        {
            //cache some bitmap and fill info in local variables for a little extra speed
            byte[] bitmapBits            = this.bitmapBits;
            bool[] pixelsChecked         = this.pixelsChecked;
            byte[] byteFillColor         = this.byteFillColor;
            int    bitmapPixelFormatSize = this.bitmapPixelFormatSize;
            int    bitmapWidth           = this.bitmapWidth;

            //***Find Left Edge of Color Area
            int lFillLoc = x;                               //the location to check/fill on the left
            int idx      = CoordsToByteIndex(ref x, ref y); //the byte index of the current location
            int pxIdx    = (bitmapWidth * y) + x;           //CoordsToPixelIndex(x,y);

            while (true)
            {
                //**fill with the color
                //bitmapBits[idx] = byteFillColor[0];
                //bitmapBits[idx + 1] = byteFillColor[1];
                //bitmapBits[idx + 2] = byteFillColor[2];
                // fill the color with alpha blend
                bitmapBits[idx]     = (byte)BlendColor(byteFillColor[0], byteFillColor[3], bitmapBits[idx], bitmapBits[idx + 3]);
                bitmapBits[idx + 1] = (byte)BlendColor(byteFillColor[1], byteFillColor[3], bitmapBits[idx + 1], bitmapBits[idx + 3]);
                bitmapBits[idx + 2] = (byte)BlendColor(byteFillColor[2], byteFillColor[3], bitmapBits[idx + 2], bitmapBits[idx + 3]);
                bitmapBits[idx + 3] = (byte)BlendAlpha(byteFillColor[3], bitmapBits[idx + 3]);
                //**indicate that this pixel has already been checked and filled
                pixelsChecked[pxIdx] = true;
                //**de-increment
                lFillLoc--;                   //de-increment counter
                pxIdx--;                      //de-increment pixel index
                idx -= bitmapPixelFormatSize; //de-increment byte index
                //**exit loop if we're at edge of bitmap or color area
                // if (lFillLoc <= 0 || (pixelsChecked[pxIdx]) || !CheckPixel(ref idx))
                if (lFillLoc <= 0 || (pixelsChecked[pxIdx]) || !CheckPixel(ref idx))
                {
                    break;
                }
            }
            lFillLoc++;

            //***Find Right Edge of Color Area
            int rFillLoc = x; //the location to check/fill on the left

            idx   = CoordsToByteIndex(ref x, ref y);
            pxIdx = (bitmapWidth * y) + x;
            while (true)
            {
                //fill with the color
                //bitmapBits[idx] = byteFillColor[0];
                //bitmapBits[idx + 1] = byteFillColor[1];
                //bitmapBits[idx + 2] = byteFillColor[2];
                // fill the color with alpha blend
                bitmapBits[idx]     = (byte)BlendColor(byteFillColor[0], byteFillColor[3], bitmapBits[idx], bitmapBits[idx + 3]);
                bitmapBits[idx + 1] = (byte)BlendColor(byteFillColor[1], byteFillColor[3], bitmapBits[idx + 1], bitmapBits[idx + 3]);
                bitmapBits[idx + 2] = (byte)BlendColor(byteFillColor[2], byteFillColor[3], bitmapBits[idx + 2], bitmapBits[idx + 3]);
                bitmapBits[idx + 3] = (byte)BlendAlpha(byteFillColor[3], bitmapBits[idx + 3]);
                //**indicate that this pixel has already been checked and filled
                pixelsChecked[pxIdx] = true;
                //**increment
                rFillLoc++;                   //increment counter
                pxIdx++;                      //increment pixel index
                idx += bitmapPixelFormatSize; //increment byte index
                //**exit loop if we're at edge of bitmap or color area
                if (rFillLoc >= bitmapWidth || pixelsChecked[pxIdx] || !CheckPixel(ref idx))
                {
                    break;
                }
            }
            rFillLoc--;

            //add range to queue
            FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);

            ranges.Enqueue(ref r);
        }