Inkscape now has a very rudimentary flood fill tool. It works by performing a bitmap-based flood fill on a rendered version of the visible canvas, then tracing the resulting fill using potrace and placing the traced path on the canvas. You can access it by the paint bucket icon in the toolbar. It places the rendered path onto the current layer, so you can have a layer on top (in my case, "Inks") and select the layer below ("Colors") and do the fills so that they always appear below the inks.
This tool is in a very basic state, and there are issues with rendering accuracy and memory usage. Some improvements that I can see being done are:
* If the [Ctrl] key is held down, clicking on an object changes the fill color to the current fill color, and [Shift]-[Ctrl] changes the stroke color to the current stroke color * A way to either manually or dynamically increase the resolution of the rendered version so that the accuracy of the flood fill is better
Try it and let me know what you think.
Thanks,
John
On 2/25/07, John Bintz <jcoswell@...1414...> wrote:
Inkscape now has a very rudimentary flood fill tool. It works by performing a bitmap-based flood fill on a rendered version of the visible canvas, then tracing the resulting fill using potrace and placing the traced path on the canvas.
Excellent work, thanks! Already very useful.
This tool is in a very basic state, and there are issues with rendering accuracy and memory usage. Some improvements that I can see being done are:
- If the [Ctrl] key is held down, clicking on an object changes the fill
color to the current fill color, and [Shift]-[Ctrl] changes the stroke color to the current stroke color
Yes. This should behave exactly like drag-dropping a color from the palette onto drawing (i.e. disregard selection and grouping). You can just pick the code from there and reuse in your tool.
- A way to either manually or dynamically increase the resolution of the
rendered version so that the accuracy of the flood fill is better
I think this can be fixed very simply. Instead of rendering the bitmap always at 100%, render it at the current zoom. This makes sense - since our tool is already "perceptual", it's not a bad thing for its results to depend on how you view your image. If you need more precision, just zoom in closer.
This presents another problem, however: if you're zoomed in too closely, rendering the entire image at this zoom may become prohibitively slow. To work around that, I propose to render not the entire drawing but only its visible part plus, say, 20% on each of the four sides. That will render about as fast as screen redraw. This means you won't be able to fill in a big area while zooming in to only a part of it, and you'll need to zoom out to see all of the area. But I think it's a reasonable choice; by zooming in and out, you will be able to find the exact balance between the coverage and precision.
More todos on the tool:
- we need a better icon for it - icon artists anyone?
- we need a matching b/w mouse cursor for the tool
- we also need some kind of "hourglass" mouse cursor that is displayed as soon as you click on the canvas until the shape creation is finished (it may well be used for some other tools/commands as well)
- we need a toolbar control for setting sensitivity threshold of the flood
- do we decide to call it "Flood tool"? or better "Paintbucket"?
- please add a section to doc/keys.xml describing all the shortcuts of the tool
Also I think we should do the right thing when one drags, not clicks, with this tool. Namely, it should convert the path along which the user dragged into a sequence of points (distanced no farther apart than 1 screen pixel at the current zoom) and make flooding from ALL these points, presenting the combined result. This way, if you have an area filled with some gradient, you just drag _along_ the gradient, and the entire area gets filled without the need to lower sensitivity of the flooding to cover the gradient.
bulia byak wrote:
- If the [Ctrl] key is held down, clicking on an object changes the fill
color to the current fill color, and [Shift]-[Ctrl] changes the stroke color to the current stroke color
Yes. This should behave exactly like drag-dropping a color from the palette onto drawing (i.e. disregard selection and grouping). You can just pick the code from there and reuse in your tool.
I'm busy for the beginning of this week, so I'll look into this later this week.
- A way to either manually or dynamically increase the resolution of the
rendered version so that the accuracy of the flood fill is better
I think this can be fixed very simply. Instead of rendering the bitmap always at 100%, render it at the current zoom. This makes sense - since our tool is already "perceptual", it's not a bad thing for its results to depend on how you view your image. If you need more precision, just zoom in closer.
This presents another problem, however: if you're zoomed in too closely, rendering the entire image at this zoom may become prohibitively slow. To work around that, I propose to render not the entire drawing but only its visible part plus, say, 20% on each of the four sides. That will render about as fast as screen redraw. This means you won't be able to fill in a big area while zooming in to only a part of it, and you'll need to zoom out to see all of the area. But I think it's a reasonable choice; by zooming in and out, you will be able to find the exact balance between the coverage and precision.
This sounds good. Where is the existing transformation that decides how much of the screen to repaint? I'll most likely end up reusing that one.
- we need a toolbar control for setting sensitivity threshold of the
flood
I'll need to implement the threshold code, but that's really simple to do. Is adding the preference for this the same as adding the preference for the tool fill/stroke style?
- do we decide to call it "Flood tool"? or better "Paintbucket"?
I would lean towards "Paint Bucket".
- please add a section to doc/keys.xml describing all the shortcuts of
the tool
OK, I'll add this later this week, as well.
Thanks,
John
On 2/26/07, John Bintz <jcoswell@...1414...> wrote:
This sounds good. Where is the existing transformation that decides how much of the screen to repaint? I'll most likely end up reusing that one.
See desktop->current_zoom() and desktop->get_display_area() - these are all you need.
- we need a toolbar control for setting sensitivity threshold of the
flood
I'll need to implement the threshold code, but that's really simple to do. Is adding the preference for this the same as adding the preference for the tool fill/stroke style?
Not quite, but close - just copy code for any spinbutton from e.g. rect tool in toolbox.cpp.
Meanwhile I moved the tool's button to a more appropriate (I think) place in the main toolbox.
- do we decide to call it "Flood tool"? or better "Paintbucket"?
I would lean towards "Paint Bucket".
Me too.
I also assigned a keyboard shortcut to the new tool: Shift+F7 or 'u'.
bulia byak wrote:
I think this can be fixed very simply. Instead of rendering the bitmap always at 100%, render it at the current zoom. This makes sense - since our tool is already "perceptual", it's not a bad thing for its results to depend on how you view your image. If you need more precision, just zoom in closer.
This is now implemented. Let me know how it works.
John
On 2/26/07, John Bintz <jcoswell@...1414...> wrote:
This is now implemented. Let me know how it works.
Thanks, works perfectly. I increased padding a little bit.
Perhaps running into the edge of the padded display area should not really trigger the "area is not bounded" abort. Only when you are past the edge of the entire image's bbox should this alert be fired; otherwise just create a path with partially rectangular edges (and maybe display the warning, e.g. "only the visible part of the area was filled", but let it be only a warning). What do you think?
bulia byak wrote:
Perhaps running into the edge of the padded display area should not really trigger the "area is not bounded" abort. Only when you are past the edge of the entire image's bbox should this alert be fired; otherwise just create a path with partially rectangular edges (and maybe display the warning, e.g. "only the visible part of the area was filled", but let it be only a warning). What do you think?
I'd rather want to trigger a different warning along the lines of "Try zooming out." I think the user's expectation should be that the Paint Bucket only fills closed bounded areas, and having it behave differently in some circumstances would become confusing.
John
On 2/27/07, John Bintz <jcoswell@...1414...> wrote:
bulia byak wrote:
Perhaps running into the edge of the padded display area should not really trigger the "area is not bounded" abort. Only when you are past the edge of the entire image's bbox should this alert be fired; otherwise just create a path with partially rectangular edges (and maybe display the warning, e.g. "only the visible part of the area was filled", but let it be only a warning). What do you think?
I'd rather want to trigger a different warning along the lines of "Try zooming out."
Yes. But I think we should still draw the shape _and_ display a warning, for example:
Only the visible part of the bounded area was filled. If you want to fill all of the area, undo, zoom out, and fill again.
I think this warning will be rarely seen, usually when there's an unnoticed gap.
bulia byak said:
On 2/27/07, John Bintz <jcoswell@...1414...> wrote:
I'd rather want to trigger a different warning along the lines of "Try zooming out."
Yes. But I think we should still draw the shape _and_ display a warning, for example:
Only the visible part of the bounded area was filled. If you want to fill all of the area, undo, zoom out, and fill again.
I think this warning will be rarely seen, usually when there's an unnoticed gap.
This works for me. It should also help the user find the gap.
John
John,
Thanks for adding the tolerance control! But what units does it use? Can we switch it to display % instead of the unnamed integers? I think it will be much more intuitive.
Also there's a small bug: when the parent or ancestor layers/groups have transforms, the fill shape gets inserted with a wrong transform (out of place). You need to find out the accumulated ancestor transform and, before inserting, transform your shape by inverse of that, so it is placed correctly. I think you can find a sample code for that in the paste command in selection-chemistry.cpp.
Two more ideas:
- inset/outset control: a spinbutton with units selector setting the distance that the resulting path is in/outset.
- Shift+click does the same as simple click but as a final step, unions the result with the currently selected path. This way, if your first click didn't cover all of the area you intended to cover, no need to undo and redo with lower tolerance; just shift+click in the remaining corner to grow your fill shape!
bulia byak wrote:
Thanks for adding the tolerance control! But what units does it use? Can we switch it to display % instead of the unnamed integers? I think it will be much more intuitive.
It was using the RGBA pixel color distances ( ( abs(original - checked)
tolerance ) == different from original ), but yeah, percentage makes
more sense. That's now changed and the conversion to pixel color distance is done in flood-context.cpp. I couldn't figure out how to get the percentage sign to appear in there, though.
Also there's a small bug: when the parent or ancestor layers/groups have transforms, the fill shape gets inserted with a wrong transform (out of place). You need to find out the accumulated ancestor transform and, before inserting, transform your shape by inverse of that, so it is placed correctly.
...and this should be working now, too. Let me know if you have any problems with either.
Take care,
John
On 2/27/07, John Bintz <jcoswell@...1414...> wrote:
Also there's a small bug: when the parent or ancestor layers/groups have transforms, the fill shape gets inserted with a wrong transform (out of place). You need to find out the accumulated ancestor transform and, before inserting, transform your shape by inverse of that, so it is placed correctly.
...and this should be working now, too.
Does not work for me on the following image:
http://upload.wikimedia.org/wikipedia/en/3/31/Winvistas.svg
which has a transform on the current layer. The fill shape appears below the logo if I click on the logo.
Also, in that image, with tolerance=67, if I click once on the green segment, undo, then click there again (sometimes it takes more than one try), Inkscape freezes eating all memory. If I break it in gdb I get:
#0 0x40eaf566 in mallopt () from /lib/tls/libc.so.6 #1 0x40eadaf9 in malloc () from /lib/tls/libc.so.6 #2 0x40e16cee in operator new () from /usr/lib/libstdc++.so.6 #3 0x08244628 in std::deque<NR::Point, std::allocatorNR::Point
::_M_push_back_aux (
this=0xbfffdfa0, __t=@0x49) at new_allocator.h:81 #4 0x082428fd in try_add_to_queue (fill_queue=0xbfffdfa0, px=0x40f67b20 "\001", orig=0xbfffde2c "ёйVЪЬ\213с\t═к╕\t", x=881, y=627, width=1925, tolerance=73) at stl_deque.h:1018 #5 0x08243795 in sp_flood_context_root_handler (event_context=0x273, event=0x8f052d0) at flood-context.cpp:466 #6 0x0823b606 in sp_event_context_root_handler (event_context=0x8c7e710, event=0x8f052d0) at event-context.cpp:796 #7 0x0823b64c in sp_event_context_item_handler (event_context=0x8c7e710, item=0x96c5870, event=0x8f052d0) at event-context.cpp:814
...i.e. it looks like it runs amok allocating an insane number of points.
Two more bugs:
With tolerance 0, draw a closed shape with calligraphic, paint black, and set 50% opacity. Paint bucket inside it. It says area is unbounded and cannot be filled - although the shape is clearly visible, and especially at zero tolerance it must be filled correctly.
Now make this shape opaque and paint it white. It is invisible, i.e. paint bucket must rightfully fail. Yet it succeeds!
I think both these bugs are caused by a wrong interpretation of colors. When you render the image to an arena, empty areas are fully transparent - but they are transparent black. It looks like you just interpret them as black - which is wrong. Instead you need to compose the arena with the canvas background color which is stored in NamedView, which is normally (but not always) transparent black, and the "under the background" color which is always opaque white. That is, there are three layers: always-white, background (which can be transparent to some degree or opaque), and the drawing. One way to properly compose that is by filling the pixblock you create for rendering arena with the proper background color (always-white composed with the background color/opacity, giving a fully opaque result) before you render into it, as is done in sp_export_get_rows for bitmap export.
Also, after the change to 0..100, the tolerance seems to no longer work - I get the same fill no matter what tolerance I set.
bulia byak wrote:
Also, in that image, with tolerance=67, if I click once on the green segment, undo, then click there again (sometimes it takes more than one try), Inkscape freezes eating all memory.
...i.e. it looks like it runs amok allocating an insane number of points.
I just optimized the fill routine to only scan adjacent pixel runs once. It now allocates a lot less items in the point queue, and runs a bit faster as well. Let me know if you are still having problems.
John
On 2/28/07, John Bintz <jcoswell@...1414...> wrote:
...i.e. it looks like it runs amok allocating an insane number of points.
I just optimized the fill routine to only scan adjacent pixel runs once. It now allocates a lot less items in the point queue, and runs a bit faster as well. Let me know if you are still having problems.
Yes I am :(
- open Winwistas.svg (I sent you link yesterday)
- press u
- tolerance = 67
- click in the topmost point of the logo but inside the frame (a couple pixels lower than the frame)
- freezes, sucking all memory :(
bulia byak wrote:
On 2/28/07, John Bintz <jcoswell@...1414...> wrote:
...i.e. it looks like it runs amok allocating an insane number of
points. I just optimized the fill routine to only scan adjacent pixel runs once. It now allocates a lot less items in the point queue, and runs a bit faster as well. Let me know if you are still having problems.
Yes I am :(
OK, I added another bitmap check. The already-rendered bitmap is also checked to see if the pixel is added. I wasn't 100% sure I would need the check, but it looks like I did. With the new code, those instructions you sent me no longer locks up Inkscape, and the fill proceeds as expected on my machine.
John
On 3/1/07, John Bintz <jcoswell@...1414...> wrote:
OK, I added another bitmap check. The already-rendered bitmap is also checked to see if the pixel is added. I wasn't 100% sure I would need the check, but it looks like I did. With the new code, those instructions you sent me no longer locks up Inkscape, and the fill proceeds as expected on my machine.
Yes, now it's fixed, thanks a lot!
One more thing I'd like to see in this tool: tracing in HSL channels. That is, have a "Fill by:" label and H, S, L checkboxes in the controls bar. By default all of them are on and this gives the same result as now. But I can leave only H on and trace a blue area on a red background, even if they are very close in S and L. Or have only S checked and trace a bunch of bright flowers on a dull (low saturation) background. Or have only L and trace the area of similar level of lightness ignoring differences in hue or saturation. I think that would be quite useful in many cases.
bulia byak wrote:
One more thing I'd like to see in this tool: tracing in HSL channels. That is, have a "Fill by:" label and H, S, L checkboxes in the controls bar. By default all of them are on and this gives the same result as now. But I can leave only H on and trace a blue area on a red background, even if they are very close in S and L. Or have only S checked and trace a bunch of bright flowers on a dull (low saturation) background. Or have only L and trace the area of similar level of lightness ignoring differences in hue or saturation. I think that would be quite useful in many cases.
How about a more generic "Use Channels" selector, so that you can choose between channels in RGB, CMYK, or HSL, and whether or not you want to use alpha in the calculations?
John
On 3/1/07, John Bintz <jcoswell@...1414...> wrote:
How about a more generic "Use Channels" selector, so that you can choose between channels in RGB, CMYK, or HSL, and whether or not you want to use alpha in the calculations?
Yes. A drop-down labeled "Fill by":
Visible color [default] Hue Saturation Lightness Red Green Blue Alpha [for this one, you will need to skip the pre-filling of the buffer with the background color]
bulia byak wrote:
On 2/27/07, John Bintz <jcoswell@...1414...> wrote:
bulia byak wrote:
Perhaps running into the edge of the padded display area should not really trigger the "area is not bounded" abort. Only when you are past the edge of the entire image's bbox should this alert be fired; otherwise just create a path with partially rectangular edges (and maybe display the warning, e.g. "only the visible part of the area was filled", but let it be only a warning). What do you think?
I'd rather want to trigger a different warning along the lines of "Try zooming out."
Yes. But I think we should still draw the shape _and_ display a warning, for example:
Only the visible part of the bounded area was filled. If you want to fill all of the area, undo, zoom out, and fill again.
This should work now. Try it and let me know what you think.
John
Hi,
I have two points with this new tool:
1) It is misleading to call the tool "flood fill", because it doesn't fill something with a color but creates a new object. We could call it "Create by color" or perhaps someone has a really good name. ;)
2) In the "Fuzzy Selection Tool" in Gimp I can control the threshold of similarity by dragging the mouse downward or to the right: the farther I drag it, the larger the selected region. And I can reduce the selection by dragging upwards or to the left. That is really helpful, so I don't need to click, undo, change threshold, click again, undo ... It would be very useful to control the tolerance in Inkscape the same way. 2a) Perhaps you can even rename tolerance to threshold so Inkscape and Gimp have the same wording.
Regards, Tobias
On 3/10/07, Tobias Jakobs <tobias.jakobs@...128...> wrote:
Hi,
I have two points with this new tool:
- It is misleading to call the tool "flood fill", because it doesn't
fill something with a color but creates a new object. We could call it "Create by color" or perhaps someone has a really good name. ;)
Actually we already renamed it to Paint Bucket which seems to be a more common name for this type of tool. But the name is not that important - it's not too prominent in the UI. The icon is more important.
- In the "Fuzzy Selection Tool" in Gimp I can control the threshold of
similarity by dragging the mouse downward or to the right: the farther I drag it, the larger the selected region. And I can reduce the selection by dragging upwards or to the left. That is really helpful, so I don't need to click, undo, change threshold, click again, undo ... It would be very useful to control the tolerance in Inkscape the same way.
Unfortunately our filling is not done sufficiently fast for such re-filling on the fly.
2a) Perhaps you can even rename tolerance to threshold so Inkscape and Gimp have the same wording.
Yes, sounds good.
Am Samstag, den 10.03.2007, 19:37 -0400 schrieb bulia byak:
On 3/10/07, Tobias Jakobs <tobias.jakobs@...128...> wrote:
Hi,
I have two points with this new tool:
- It is misleading to call the tool "flood fill", because it doesn't
fill something with a color but creates a new object. We could call it "Create by color" or perhaps someone has a really good name. ;)
Actually we already renamed it to Paint Bucket which seems to be a more common name for this type of tool. But the name is not that important - it's not too prominent in the UI. The icon is more important.
Paint Bucket is really a much better name and you are right the icon is much more important then the name. The aktuell icon looks nice but I think we need a better metaphor.
- In the "Fuzzy Selection Tool" in Gimp I can control the threshold of
similarity by dragging the mouse downward or to the right: the farther I drag it, the larger the selected region. And I can reduce the selection by dragging upwards or to the left. That is really helpful, so I don't need to click, undo, change threshold, click again, undo ... It would be very useful to control the tolerance in Inkscape the same way.
Unfortunately our filling is not done sufficiently fast for such re-filling on the fly.
I'm not a programmer, so I don't know why it's so slow. If it's the tracing I think we don't need it to show a preview here. The preview could be completely pixel based. Perhaps you can even use the selection to path code from Gimp here so you don't need potrace, if that's faster.
Tobias
On 2/27/07, bulia byak <buliabyak@...400...> wrote:
On 2/26/07, John Bintz <jcoswell@...1414...> wrote:
This is now implemented. Let me know how it works.
Thanks, works perfectly. I increased padding a little bit.
Perhaps running into the edge of the padded display area should not really trigger the "area is not bounded" abort. Only when you are past the edge of the entire image's bbox should this alert be fired; otherwise just create a path with partially rectangular edges (and maybe display the warning, e.g. "only the visible part of the area was filled", but let it be only a warning). What do you think?
Yes really nice ! I agree that the abort is a bit confusing, I didn't notice the message in the status bar at first.
Romain
John Bintz wrote:
This tool is in a very basic state, and there are issues with rendering accuracy and memory usage. Some improvements that I can see being done are:
When you try to fill blurred shapes, the path comes out very jaggy. Perhaps there should be some way to control the path optimisation setting for potrace?
It's a very cool toy. I'm sure I'll be able to find a use for it once I get my head around the strangeness of it.
Dan
On 2/26/07, Daniel Pope <mauve@...1559...> wrote:
When you try to fill blurred shapes, the path comes out very jaggy.
I'm wondering if this jagginess really comes from potrace, or is it already present in the flood bitmap that it traces?
participants (5)
-
bulia byak
-
Daniel Pope
-
John Bintz
-
Romain Thouvenin
-
Tobias Jakobs