Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Auto fit brush to image?
#1
Hello.

I sometimes use a set of grunge brushes which tile seamlessly. Very good for game textures and other 3d scenes. To fit them to the image currently requires a couple of steps which I'd prefer to simplify:

1. Manually set brush size to image size (this usually applies to square images so the size value on its own is usually enough).


2. Create horizontal and vertical guides at 50% each (or zoom in and be careful). I recently installed a guides plugin which makes this a little easier.
Another option I read about was to set up the grid so that its lines cross at the centre, but that's quite a few steps and some people might want the grid for other uses.

The above may only be 2 steps but I may have several layers with different grunge brushes, and/or be making several images, so those 2 steps can multiply quite quickly. Some repetition will be needed if, between adding grunge brushes, I change the brush size for other things (e.g. eraser, painting, cloning etc).

Does anyone know if there are any addons that could simplify the above process? If not, I'd be happy to raise a feature request on the GNome page for 3.2 (I'm aware that 3.0 is now having just it's existing features tweaked, which makes sense).
Reply
#2
(01-14-2024, 01:21 PM)R Soul Wrote: Hello.

I sometimes use a set of grunge brushes which tile seamlessly. Very good for game textures and other 3d scenes. To fit them to the image currently requires a couple of steps which I'd prefer to simplify:

1. Manually set brush size to image size (this usually applies to square images so the size value on its own is usually enough).

Which image? The target image or the image used as a brush? if the former, you are using a single brush stroke in the whole image (then why a brush?), if the later, there is a reset button in the Tool options to reset the brush to its native size (and if you switch the brush, the size is reset to the native size of the new brush).

(01-14-2024, 01:21 PM)R Soul Wrote: 2. Create horizontal and vertical guides at 50% each (or zoom in and be careful). I recently installed a guides plugin which makes this a little easier.
Another option I read about was to set up the grid so that its lines cross at the centre, but that's quite a few steps and some people might want the grid for other uses.

The above may only be 2 steps but I may have several layers with different grunge brushes, and/or be making several images, so those 2 steps can multiply quite quickly. Some repetition will be needed if, between adding grunge brushes, I change the brush size for other things (e.g. eraser, painting, cloning etc).

Does anyone know if there are any addons that could simplify the above process? If not, I'd be happy to raise a feature request on the GNome page for 3.2 (I'm aware that 3.0 is now having just it's existing features tweaked, which makes sense).

Not very hard to make a script that makes an appropriately centered grid that matches the current brush size... (which IMHO is more practical than guides, because you would have to remove all existing guides each time you change a brush and these do have other purposes). For extra credit: should the grid be aligned with the image or with the active layer?
Reply
#3
(01-14-2024, 02:10 PM)Ofnuts Wrote: Which image? The target image or the image used as a brush? if the former, you are using a single brush stroke in the whole image (then why a brush?), if the later, there is a reset button in the Tool options to reset the brush to its native size (and if you switch the brush,  the size is reset to the native size of the new brush).
The target image. The reason for using a brush/single stroke is that these things are already brushes. See here for their website: https://www.deviantart.com/redheadstock/...s-65840762

Quote:Not very hard to make a script that makes an appropriately centered grid that matches the current brush size... (which IMHO is more practical than guides, because you would have to remove all existing guides each time you change a brush and these do have other purposes). For extra credit: should the grid be aligned with the image or with the active layer?

It might be easier to show what I'm currently doing by posting screenshots:
1. Load some base image, could be any size but I'd usually make them sqaure or nearst power of 2 for typical game requirements:
[Image: grunge_addtion_1.jpg]

2. Choose the desired grunge brush. Note it's 1000x1000. Some base images will be a lot bigger or smaller, so resizing them to match the brush isn't always ideal.[Image: grunge_addtion_2.jpg]

3. Resize the brush to match the image size, and add guides:
[Image: grunge_addtion_3.jpg]

4. Paint. Sometimes multiple clicks/strokes to get more boldness (or edit layer colours/alpha afterwards):
[Image: grunge_addtion_4.jpg]
Reply
#4
OK, so what you really want is something that takes a brush, scales it to the size of a layer/image, and then strokes it on the current layer?
Reply
#5
That's right. Initially my expectation was that the user would stroke the brush, but it makes sense to include one stroke in the script as it removes the need for adding guidelines. If there's nothing out there I could have a go at writing my own. I've written some python addons for Blender but my Gimp scripting experience is quite low.
Reply
#6
Already done. See ofn-brush-to-layer just uploaded here.
Reply
#7
I've got a barebones bit of python code - it sets the brush size and works out the centre coords.

I'v highlighted in red where I'm stuck.
Aspect ratio: not sure what the maths is here

Drawing/stroking: not sure what are valid parameters, correct syntax etc.


Menu location: similarly, not sure of correct menu placement code.

from gimpfu import *

def add_scaled_brush(img, layer):
    # Set up an undo group, so the operation will be undone in one step.
    pdb.gimp_undo_push_group_start(img)

    # Do stuff here.
    xCentre = img.width/2
    yCentre = img.height/2

    brushSize = float(img.width)
    pdb.gimp_context_set_brush_size(brushSize)
    
    aspectRatio = 0.0 #TO DO - calculate based on image height
    pdb.gimp_context_set_brush_aspect_ratio(aspectRatio)
    
    newLayer = pdb.gimp_layer_new(img, img.width, img.height, RGBA_IMAGE, "Scaled Brush", 100.0, LAYER_MODE_NORMAL)
    pdb.gimp_image_insert_layer(img, newLayer, None, 0)
    
    #draw with the current brush
    #something to do with pdb.gimp_paintbrush
    
    # Close the undo group.
    pdb.gimp_undo_push_group_end(img)

register(
    "add_scaled_brush", #Name
    "Add Scaled Brush to Image", #Blurb
    "Scale current brush to image, paint once to new layer.", #help
    "R Soul", #Author
    "CC Licence", #Copyright
    "2024", #Date
    "<Image>/Image/Add Scaled Brush", #Menu path, needs to go somewhere else
    "",      # image types
    [ # No Gui Params
    ],
    [], # Results
    add_scaled_brush) #function

main()
Reply
#8
See post above yours for the crib sheet.
Reply
#9
Many thanks for your help. I see where I'd gone the wrong way with some of my values. I decided that I still want it to create a new layer automatically, so I modified your code to have it draw on a new layer which is based on the current selection and offset (changes occur after the code to set the brush size):

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# GIMP plugin to ifll the current layer with a stroke of a brush

# (c) Ofnuts 2023
#
#   History:
#
#   v0.0: 2024-01-14: Initial version
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


import sys,os,os.path,traceback,random
from gimpfu import *
import gimpcolor

debug='OFN_DEBUG' in os.environ
 
def trace(format,*args):
   if debug:
       print format % args


def strokeBrushOnLayer(image,drawable):
   #pdb.gimp_plugin_enable_precision()
   image.undo_group_start()
   gimp.context_push()
   try:        
       # Get brush data
       _, _, _, _, bw, bh, _, _ = pdb.gimp_brushes_get_brush_data("") # Data for current brush
       lw,lh=drawable.width,drawable.height
       ox,oy=drawable.offsets
       scaleX=float(lw)/bw # required for horizontal fill
       scaleY=float(lh)/bh # required for vertical fill
       scale=max(scaleX,scaleY)
       size=int(round(max(bw,bh)*scale)) # Brush size is size of biggest dimension
       trace("Brush is %dx%d, sized to %d (%5.2f)",bw,bh,size,scale)
       pdb.gimp_context_set_brush_size(size)
           
       newLayer = pdb.gimp_layer_new(image, lw, lh, RGBA_IMAGE, "Scaled Brush", 100.0, LAYER_MODE_NORMAL)
       pdb.gimp_layer_set_offsets(newLayer, ox, oy)
       pdb.gimp_image_insert_layer(image, newLayer, None, 0)
       
       pdb.gimp_paintbrush_default(newLayer, 2, [lw/2,lh/2])
       
   except Exception as e:
       print e.args[0]
       gimp.message(e.args[0])
       print traceback.format_exc()
       
   gimp.context_pop()
   image.undo_group_end()
   gimp.displays_flush()    

### Registration
author='Ofnuts'
copyrightYear='2024'
desc='Fill layer with scaled current brush'
register(
   'ofn-brush-to-layer',
   desc,desc,author,author,copyrightYear,desc+'...',
   'RGB*',
   [
       (PF_IMAGE, 'image', 'Input image', None),
       (PF_DRAWABLE, 'layer', 'Input layer', None),
   ],
   [],
   strokeBrushOnLayer,
   menu='<Image>/Test' if debug else '<Image>/Filters/Render/'
)

main()
Reply


Forum Jump: