Gimp-Forum.net

Full Version: ofn-manual-stipple
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
This plugins tries to emulate someone hammering a pen on a paper to create hand-made stippling. Basically it converts a luminance map into random paintbrush strokes:

[attachment=6642]

At its worst is can generate  lo-fi version of photographs, but the smallest visible detail is around 20x larger than the brush size and it requires a lot of preliminary tweaking:

[attachment=6641]


As usual it can be found here.

Enjoy.

PS: Old timers will notice some likeness with RobA's "Random Density Map" script. Actually the ideas are similar. The main differences are:
  • this script tries harder to be luminosity-accurate
  • this script is somewhat faster
  • this script is is not as resource intensive (RDM blows the undo stack to gigantic proportions)
  • RDM has some more functionalities
A little test with the ofn-manual-stippling plugin with a layer with a color picture and a white layer. Settings on the plugin : Brush coverage 80 / Gamma tweak 05 / Jitter 1). Then set the layer mode from the result on 'Dodge'. 
[attachment=6663]
(09-02-2021, 08:00 PM)Ofnuts Wrote: [ -> ]PS: Old timers will notice some likeness with RobA's "Random Density Map" script. Actually the ideas are similar. The main differences are...

Hiya Ofnuts!  Long time no see!

Joined the forum here just to post as I'm getting back into the world of Gimp.

Even though my "Random Density Map" script is still working under 2.10 it is tremendously slow.

As I'm still trying to figure out python, I decided to modify this plugin to add a brush spacing parameter (which I succeeded at!)
Many of the brushes I use are .gbr's that don't fill the entire brush area as returned by pdb.gimp_context_get_brush_size(), so I need the spacing to be adjusted by 50% or so.  This (of course) also required an adjustment to the jitter calculation, and also needed changing the jitter input slider to "tenths" rather than "ones".

Attached is an example of the map, with the default (100%) spacing which is what the plugin did originally, set to 50% spacing, and lastly with reduced spacing and jitter, showing how I use it with my brushes to quickly create dense forest areas having individual trees....
[attachment=9186]

If interested, I'd be happy to provide my hack if you want to update your code.

P.S. I tried to leverage your OFN_DEBUG and debug trace code but your original plugin would just throw errors with that flag on, so I obviously had no idea what I was doing or how to use it properly...

P.P.S. Is this where all the cool gimp kids hang out now?

Cheers!

-RobA>
(12-23-2022, 03:13 AM)RobA Wrote: [ -> ]
(09-02-2021, 08:00 PM)Ofnuts Wrote: [ -> ]PS: Old timers will notice some likeness with RobA's "Random Density Map" script. Actually the ideas are similar. The main differences are...

Hiya Ofnuts!  Long time no see!

Joined the forum here just to post as I'm getting back into the world of Gimp.

Even though my "Random Density Map" script is still working under 2.10 it is tremendously slow.

As I'm still trying to figure out python, I decided to modify this plugin to add a brush spacing parameter (which I succeeded at!)
Many of the brushes I use are .gbr's that don't fill the entire brush area as returned by pdb.gimp_context_get_brush_size(), so I need the spacing to be adjusted by 50% or so.  This (of course) also required an adjustment to the jitter calculation, and also needed changing the jitter input slider to "tenths" rather than "ones".

Attached is an example of the map, with the default (100%) spacing which is what the plugin did originally, set to 50% spacing, and lastly with reduced spacing and jitter, showing how I use it with my brushes to quickly create dense forest areas having individual trees....


If interested, I'd be happy to provide my hack if you want to update your code.

P.S. I tried to leverage your OFN_DEBUG and debug trace code but your original plugin would just throw errors with that flag on, so I obviously had no idea what I was doing or how to use it properly...

P.P.S. Is this where all the cool gimp kids hang out now?

Cheers!

-RobA>
  • Same. Saw your registration before your post, so wondering about an imposter Smile
  • Glad to see you are at it again.
  • Instead of having a script parameter, maybe the script could be sensitive to the brush spacing (as it is to the brush size, etc...) using pdb.gimp_context_get_brush_spacing()?
  • Of course I'm interested
  • OFN_DEBUG is an environment variable in my Bash sessions. When I try something I start Gimp in a terminal, so OFN_DEBUG appears in the Gimp environment, and therefore in the Python plugin environment. This is converted into a global boolean by debug='OFN_DEBUG' in os.environ and the trace() function checks this debug to determine if it should output things (that I will then see it in the terminal). debug has other uses (such as putting the menu entry in a place easier to use when testing, and even in some rare cases adding parameters in the dialog). A side benefit is that the code doesn't print anything when not running on the machines of the illuminatus (illuminati, now that you know) and so avoids the process hang that occurs on windows if you print more than 4K of output.
  • Coolness is in the eye of the beholder Smile GC is still alive (but maybe not kicking as much since it changed hands). The gimp-user/gimp-developer mailing lists have been recently discontinued and are replaced by the general Gnome Discourse server.
(12-23-2022, 08:56 PM)Ofnuts Wrote: [ -> ]
  • Instead of having a script parameter, maybe the script could be sensitive to the brush spacing (as it is to the brush size, etc...) using pdb.gimp_context_get_brush_spacing()?
  • Of course I'm interested

That was a great suggestion but it does pose a bit of a pickle...

If I just use:
Code:
self.brushSpacing=float(pdb.gimp_context_get_brush_spacing())

and it works the way I like (i.e. the stipple pattern will be at the spacing you get if you draw with the paintbrush so you can actual test the stipple spacing by just stroking a straight line) but this is counter-intutive to the current operation as the plugin spaces based on the brush size (i.e. 100% spacing).  The issue is that brushes that aren't  intended to be "stamps" will have a fractional spacing by default so they stoke smoothly.  So this would require users to manually change the spacing of the brush before running the plugin.

Alternately, I can use this:
Code:
self.brushSpacing=float(pdb.gimp_context_get_brush_spacing()/pdb.gimp_brush_get_spacing(pdb.gimp_context_get_brush())*100.)

to still allow the user to change the spacing of the stipple by using the ratio of the currently set spacing over the brush's default spacing.  So selecting a brush and using the default spacing will place the stipples with a spacing equal to the brush size.  To space the stipples closer or further together the user will have to select a spacing smaller or larger than the default spacing for the brush, and knowing what that will result in is somewhat counter-intuitive...

Any thoughts on the preferred option?

-RobA>
Second look:
  • ofn-manual-stippling has a "Coverage" parameter for brushes that are actually smaller than their outline. That doesn't make the strokes closer, but more likely.
  • There are really two kind of brushes, those for drawing lines (the circular "Hardness XX" for instance) that have a small spacing(<5), and those that are meant to be separate strokes (the bellpepper, the sparkles) that have a wider spacing (>20), and these may have to be handled differently. I recking than the first ones would really be used for stippling (ie, achieve some luminosity using many tiny strokes)  while the others are more in the realm of your density map
  • What could be changed using a spacing is the X/Y steppings in the stipple(self) method, but should the script use:
    • the brush native spacing
    • the spacing as set in the "context" (using the Paintbrush parameters for instance)
    • a script-specific spacing parameter
    A combination of these could also be used , for instance use the global spacing if the script spacing is set to 0
Any thoughts?