0

I am attempting to implement a flood fill tool to a WPF paint program. I am attempting to bypass any of the vector methods by making sure every drawing action is written to the bitmap first. The bitmap is then set to the canvas.

I am having an issue when passing the image to the canvas. It does not set the image using a relative position. The images will explain much better than I can.

Before Fill:

Before Fill

After Fill:

enter image description here

The image bitmap is written relative to the window and overlaps the toolbar. I am wondering how I can prevent this from happening. Attached is the relevant code from my Fill class.

    public override void OnMouseDown(CCDrawingCanvas canvas, System.Windows.Input.MouseButtonEventArgs e) {
        double dpi = 96d;

        // Get the size of the canvas
        System.Windows.Size size = new System.Windows.Size((int)canvas.ActualWidth, (int)canvas.ActualHeight);

        // Measure and arrange the surface
        canvas.Measure(size);
        canvas.Arrange(new Rect(size));

        RenderTargetBitmap source = new RenderTargetBitmap(
            (int)canvas.ActualWidth,
            (int)canvas.ActualHeight,
            dpi,
            dpi,
            PixelFormats.Pbgra32);
        source.Render(canvas);

        WriteableBitmap modifiedImage = new WriteableBitmap(source);
        int h = modifiedImage.PixelHeight;
        int w = modifiedImage.PixelWidth;
        int[] pixelData = new int[h * w];
        int widthInByte = modifiedImage.PixelWidth * (modifiedImage.Format.BitsPerPixel / 8);

        modifiedImage.CopyPixels(pixelData, widthInByte, 0);

        int oldColor = BitConverter.ToInt32(new byte[] { System.Drawing.Color.White.B, System.Drawing.Color.White.G, System.Drawing.Color.White.R, System.Drawing.Color.White.A }, 0);
        int newColor = BitConverter.ToInt32(new byte[] { System.Drawing.Color.Black.B, System.Drawing.Color.Black.G, System.Drawing.Color.Black.R, System.Drawing.Color.Black.A }, 0);

        // Perform the recursive fill
        FloodFill(pixelData, (int)p.X, (int)p.Y, w, h, oldColor, newColor);

        modifiedImage.WritePixels(new Int32Rect(0, 0, w, h), pixelData, widthInByte, 0);

        newFill = new GraphicsFill(modifiedImage);

        // Adds newFill to canvas.GraphicsList
        AddObject(canvas, newFill);

    }

XAML Code:

<Window x:Class="ccGui.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:effects="clr-namespace:System.Windows.Media.Effects;assembly=presentationcore"
    xmlns:lib="clr-namespace:ccDrawingLib;assembly=ccDrawingLib"
    xmlns:local="clr-namespace:ccGui"
    Title="MainWindow" Height="600" Width="800">

<DockPanel>
    <Menu DockPanel.Dock="Top">
        <MenuItem Header="File">
            <MenuItem Header="New" Command="ApplicationCommands.New" />
            <MenuItem Header="Open" Command="ApplicationCommands.Open" />
            <MenuItem Header="Save" Command="ApplicationCommands.Save" />
            <MenuItem Header="Save As" Command="ApplicationCommands.SaveAs" />
            <MenuItem Header="Close" Command="ApplicationCommands.Close" />
        </MenuItem>
        <MenuItem Header="Tool" Name="menuTools">
            <MenuItem Header="Brush" Name="ccToolBrush" Tag="Brush" />
            <MenuItem Header="Fill" Name="ccToolFill" Tag="Fill" />
        </MenuItem>
    </Menu>
    <lib:CCDrawingCanvas x:Name="canvas" Background="White" />
</DockPanel>
</Window>
10
  • 1
    The symptoms almost look like the new object is being added to the parent or root Visual instead of the child. In general the layout system usually prevents non-relative layouts unless you're really trying or you added to the wrong parent Visual/container. Can you share the relevant XAML too? Commented Feb 10, 2014 at 5:06
  • 1
    Why on earth would you do all that manually, when you can just use the shapes classes and save the image using the RenderTargetBitmap.Render Method? Commented Feb 10, 2014 at 9:16
  • 1
    In WPF, practically all UI controls extend the Visual class. You can use that Visual reference to pass to the RenderTargetBitmap.Render Method to easily save an image of that UI control. You should investigate it to make your life easier. Commented Feb 10, 2014 at 17:08
  • 1
    That's a very good point... I think this sentence made me jump to the wrong conclusion: I am attempting to bypass any of the vector methods by making sure every drawing action is written to the bitmap first. My point is this... I guess that you're using a Path when drawing shapes. If this is true, then can't you just use the Path.Fill property to fill it? You shouldn't need to keep switching between the Shapes and BitMapImages. Commented Feb 10, 2014 at 18:56
  • 1
    The answer to that is the Panel.Zindex Attached Property. Set each new drawn shape to use the next higher Zindex value and then the latest shapes will always sit on top of the lower ones, just as in a drawing program. Commented Feb 10, 2014 at 19:11

1 Answer 1

1

In WPF, practically all UI controls extend the Visual class. You can use that Visual reference to pass to the RenderTargetBitmap.Render Method to easily save an image of that UI control. It seems to me that you shouldn't need to keep switching between the Shapes and BitMapImages to fill your Shapes. I guess that you're using a Path when drawing shapes. If this is true, then you can just use the Path.Fill property to fill it in without having to do any manual calculations.

Furthermore, if you set the Panel.Zindex Attached Property on each new drawn shape and use the next higher Zindex value each time, then the latest shapes will always sit on top of the lower ones, just as in a drawing standard program. You could even enable the users to switch the shape layers of their drawn picture using this property.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.