Switch to full style
Ask all general Gimp related questions here
Post a reply

Multi-Fill Script Help

Sun Feb 27, 2011 1:07 am

I am wanting to take RobA's multifill script, and add a patterns option instead of just either random colors or palette colors.

The purpose of this script would be to replace selections randomly with patterns (the primary project in mind is stained glass window patterns).

I'm looking at this portion of the script to determine what changes I would need to make in order to add a new set of patterns options:
Code:
(begin
               (set! nextcolour (car (gimp-palette-entry-get-color inPalette palettecount))) ; next palette colour, - not B, W or flagcoulor
               (while (or (= (+ (car nextcolour) (cadr nextcolour) (caddr nextcolour)) 765)
                     (= (+ (car nextcolour) (cadr nextcolour) (caddr nextcolour)) 0)
                     (= (listeql? nextcolour inFlagColour) TRUE))
                   (set! palettecount (modulo (+ palettecount 1) numcolours)) ; increment palette
                  (set! nextcolour (car (gimp-palette-entry-get-color inPalette palettecount)))
               )         
               
               (set! palettecount (modulo (+ palettecount 1) numcolours)) ; increment palette
               )
            )
            (gimp-context-set-foreground nextcolour)
            )
         (gimp-context-set-foreground inFlagColour)
         )
      )


This is how the code is currently written, but I'm thinking I need to add an "if" flag for when the (palettes) option is true.

1. Is it crucial to set a statement for the other options to be false, in order for the new pattern option to be true, or is simply adding another (begin (if (= inPatterns TRUE) sufficient? My thoughts are, I wouldn't want the user to be able to make 2 or 3 options to be true at the same time. Something to flag the user that they cannot use more than one option at a time.

2. Could I continue using (nextcolour) in the same fashion with patterns as it is used in palettes and random colors, or would I need to make a new definition? (My gut says a new definition to assign patterns randomly is needed)

3. I am aware of (palettecount) so I would also need to establish a (patterncount).

4. I'm totally lost on how I would assign the script to look for a subset folder of patterns, and not the .gimp-2.6/patterns folder. I would want the ability to assign this value on the script menu, as the folder location could change for a different project.

A menu to elaborate my intentions:

Image

Re: Multi-Fill Script Help

Sun Feb 27, 2011 3:34 am

That would be a cool Script-fu if you could get it to work Mahvin. Wish I could help, but I never Script-fu and the few that I modified were simplistic little things. Might have to get RobA's help again on this one. I would be interested in it though; like the stained glass idea. :)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 3:44 am

Me too. :)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 8:49 am

Have you looked into snatching some code from the LayerFX script?
I mentioned this in the other thread too.(stained glass)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 9:31 am

mahvin wrote:1. Is it crucial to set a statement for the other options to be false, in order for the new pattern option to be true, or is simply adding another (begin (if (= inPatterns TRUE) sufficient? My thoughts are, I wouldn't want the user to be able to make 2 or 3 options to be true at the same time. Something to flag the user that they cannot use more than one option at a time.

Script-fu's dialog interface does not support the concept of "radio buttons" (where only one of a group of options can be chosen). The best alternative, in my opinion, is to use the SF-OPTION widget to provide a drop-down list.

Code:
SF-OPTION "Fill mode" '("Random colours" "Colours from palette" "Patterns from directory")

Codewise, you will probably want to use Scheme's 'cond' statement, rather than nested 'if's.

mahvin wrote:2. Could I continue using (nextcolour) in the same fashion with patterns as it is used in palettes and random colors, or would I need to make a new definition? (My gut says a new definition to assign patterns randomly is needed)

Better to treat pattern filling as a separate "fill mode", for this is what is really being done (see code below). But basically you are correct that pattern filling is little different from filling with a solid color.

mahvin wrote:3. I am aware of (palettecount) so I would also need to establish a (patterncount).

Correct. In the code below, I use a 'palettecount' variable to index into a list of all the .pat files in the specified directory. (Note: I did not attempt to randomly select patterns from the pattern directory. If you wish to provide support for such randomization, I would be glad to assist.)

mahvin wrote:4. I'm totally lost on how I would assign the script to look for a subset folder of patterns, and not the .gimp-2.6/patterns folder. I would want the ability to assign this value on the script menu, as the folder location could change for a different project.

When registering your script (script-fu-register), include an SF-DIRNAME widget.

Code:
SF-DIRNAME "Pattern directory" "/some/default/directory"

mahvin wrote:A menu to elaborate my intentions:

[snip]...

Kudos on putting so much effort into describing your expectations -- and even providing a mockup of the desired dialog (instead of merely writing down a few thousand millipictures). Clearly understanding what software is supposed to accomplish is the first step in writing the code -- and for me is the most challenging part. The time you've put into requesting help makes it much easier for those who would provide it to do so (this is true not just for coding requests, but for reporting bugs -- or seeking help in general). I would say, however, that it would have been nice had you provided a link to the location of the original script.

Since your goal seems to be learning more about scripting (and since I did not write the original script), I submit the following code fragment to demonstrate how I would approach adding such a feature. I have not tested the code (or even modified the script to attempt so). I leave it to you to incorporate the appropriate changes to your version of RobA's script (remember to add the SF-DIRNAME and SF-OPTION widgets as previously mentioned).

(Note: I did not use RobA's 'listeq?' function since the same thing can be accomplished with Scheme's 'equal?' procedure.)

Add the following variables to your 'let*' bindings:
Code:
  (patterns (cadr (file-glob (string-append inPatternDirectory DIR-SEPARATOR "*.pat"))))
  (numpatterns (length patterns)) ; NOTE: should generate error if zero
  (patterncount 0) ; index into list of patterns

The following code (or somesuch) should be substituted into the appropriate location of the original script. EDIT: this code will definitely not work. One cannot set the current active pattern based on the pattern's filename (which the file-glob provides). We will have to either extract the pattern's name from the file, or load the pattern file as an image, copy it to the clipboard, and fill using the clipboard as pattern. The second approach is probably better since it doesn't depend upon the pattern being in GIMP's path for pattern directories.

Code:
    (if (or (and (= inHowCheck 0)
                 (<= (- (cadddr bounds) (cadr bounds)) inIgnoreSize)
                 (<= (- (list-ref bounds 4) (caddr bounds)) inIgnoreSize) ) ; X and Y size
            (and (= inHowCheck 1)
                 (<= (cadddr (gimp-histogram inLayer HISTOGRAM-VALUE 0 255)) inIgnoreSize) )) ; area
      (begin
        (gimp-context-set-foreground (list 0 0 0)) ; fill with black - will be ignored in flatten step
        (gimp-edit-fill inLayer FOREGROUND-FILL) )
      (if (or (and (= inHowCheck 0)
                   (> (- (cadddr bounds) (cadr bounds)) inFlagSize)
                   (> (- (list-ref bounds 4) (caddr bounds)) inFlagSize) ) ; X and Y size
              (and (= inHowCheck 1)
                   (> (cadddr (gimp-histogram inLayer HISTOGRAM-VALUE 0 255)) inFlagSize) )) ; area
        (cond
          ((= fill-type 0) ; Random color fill
            (set! nextcolour inFlagColour) ; guarantees 'while' will loop at least once
            (while (equal? nextcolour inFlagColour) ; random color must not be the flag color
              (set! nextcolour (list (+ (rand 254) 1) ; not black or white either
                                     (+ (rand 254) 1) ; hence color is ([1-254],[1-254],[1-254])
                                     (+ (rand 254) 1) )))
            (gimp-context-set-foreground nextcolour)
            (gimp-edit-fill inLayer FOREGROUND-FILL)
            )
          ((= fill-type 1) ; get color from palette
            (set! nextcolour (car (gimp-palette-entry-get-color inPalette palettecount))) ; next palette colour, - not B, W or flagcoulor
            (while (or (= (apply + nextcolour) 765)
                       (= (apply + nextcolour) 0)
                       (equal? nextcolour inFlagColour) )
              (set! palettecount (modulo (+ palettecount 1) numcolours)) ; increment palette
              (set! nextcolour (car (gimp-palette-entry-get-color inPalette palettecount))) )
            (set! palettecount (modulo (+ palettecount 1) numcolours))
            (gimp-context-set-foreground nextcolour)
            (gimp-edit-fill inLayer FOREGROUND-FILL) )
          ((= fill-type 2) ; fill with a pattern from specified directory
            (gimp-context-set-pattern (list-ref patterns patterncount))
            (gimp-edit-fill inLayer PATTERN-FILL)
            (set! patterncount (modulo (+ patterncount 1) numpatterns)) ))
        (gimp-context-set-foreground inFlagColour) ))

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:19 am

saulgoode wrote:

mahvin wrote:3. I am aware of (palettecount) so I would also need to establish a (patterncount).

Correct. In the code below, I use a 'palettecount' variable to index into a list of all the .pat files in the specified directory. (Note: I did not attempt to randomly select patterns from the pattern directory. If you wish to provide support for such randomization, I would be glad to assist.)


Why only the .pat files ?
Gimp may use also pattern in jpg, png,and gif(not sure about tif)

on the other hand i didn't see in the script any limitation to the pat format (maybe there is but i just didn't notice )

Re: Multi-Fill Script Help

Sun Feb 27, 2011 11:44 am

The following code will assign a list of pattern names to a variable 'patterns'. It is not very robust (it doesn't check for non-existent files and could stall if the file is corrupt or not a pattern), but it should be sufficient for initial experimentation. Of course, the pattern file must be in GIMP's search path for patterns in order that 'gimp-context-set-pattern' will be able to specify it as the current active pattern.

Code:
(set! patterns (map
      (lambda (filename)
        (let* ((port (open-input-file filename))
               (ch #\a)
               (magic "    ")
               (name "") )
          (while (not (string=? magic "GPAT"))
            (set! ch (read-char port))
            (set! magic (string-append (substring magic 1)
                                       (make-string 1 (if (equal? ch #\x0) #\space ch)) )))
          (set! ch (read-char port))
          (while (not (equal? ch #\x0))
            (set! name (string-append name (make-string 1 ch)))
            (set! ch (read-char port)) )
          (close-input-port port)
          name ))
    (cadr (file-glob (string-append inPatternDirectory DIR-SEPARATOR "*.pat") 1))))

Re: Multi-Fill Script Help

Sun Feb 27, 2011 2:58 pm

The flatting and multi-fill tool is located at the registry here (I love this script by the way, a comic panel artist's best friend!):

http://registry.gimp.org/node/14051

I stay up too late sometimes, and the mind gets fuzzy.

Thanks for the heads up, Saulgoode, I'll will definitely play around with this code a bit to see how much damage I can do. :)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 3:16 pm

Oh wow, I'm not going to kid myself here, this is way over my head. I will definitely need your help, Saulgoode. I need to be able to break this down so that I can at least understand why I am setting up or using code in this form. It's a daunting task and a lot for me to ask of you, but the scheme tutorials online are limited to simple tasks and automation. Are there more intermediate level tutorials somewhere online that takes you into this area of scheme? My search results usually land on the "hello world" variety, and that's too much milk for someone needing a little more solid food.

Some script-fu guru should write a book, I know they'll make a fortune.

Re: Multi-Fill Script Help

Sun Feb 27, 2011 3:22 pm

The following code will assign a list of pattern names to a variable 'patterns'. It is not very robust (it doesn't check for non-existent files and could stall if the file is corrupt or not a pattern), but it should be sufficient for initial experimentation. Of course, the pattern file must be in GIMP's search path for patterns in order that 'gimp-context-set-pattern' will be able to specify it as the current active pattern.


So, simply adding an additional path in Edit - Preferences for patterns search would resolve this? I have a small problem with this for other people using this script, requiring them to take additional steps might cause confusion. Is there a more global method to use a script to set that step? Not sure if I am asking in the right way, but I am curious if a script could actually set preferences?

Re: Multi-Fill Script Help

Sun Feb 27, 2011 4:55 pm

Maybe i didn't understand well...I don't see much a problem here

Just in case the user find too hard create a new path he may anyway use 1 of the 2 default paths,( the first for pattern included by default and the second for the patterns (maybe) added in his gimp user directory)

then the user remain free to create new paths in preference as suggested

but if he doesn't that 2 paths always exist and more important the first always contain something so maybe the first path in preference may be used as default

to the user the possibility to make a more advanced use of the script , creating new folder(s) for patterns
and link them from Preferences... if doesn't his possibilty to chose will be limited to the default paths, but the script will work, maybe not at his best but without errors

Re: Multi-Fill Script Help

Sun Feb 27, 2011 5:34 pm

PC:

I've learned the hard way that problems come easy to people in the simplest of ways. For instance, if the script remains dormant (unused) for a period of time and the user returns to use it again, having made changes since the last time they used it, it could be problematic. For me and you, and others of our mindset, maybe not so much, but a fresh out of the box noob, perhaps more so. I'd want flags to prompt the user if something needs to be done, like a reminder to set up a pointer to a pattern folder. This is just to prevent an error from scaring the user into thinking the script is broken and avoiding all that "blah blah blah" your script doesn't work" scenarios.

Re: Multi-Fill Script Help

Sun Feb 27, 2011 6:49 pm

I found this, for starters: http://community.schemewiki.org/?scheme-style

Plus, I clicked your cond link above (that information seems to be geared to those who already know scheme, in advanced)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 8:08 pm

I applied all your recommendations, and got it to register, but I see a conflict between the ability to select your directory and declaring a directory name (at least I think it's a conflict).

I also get this error when attempting to use patterns:

Image

EDIT: Fixed this by putting the palette back in. Heh!

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:03 pm

Mahvin
i really don't know script fu, i just try to use lateral thinking, but i fear i may wrote some nonsense

but I see a conflict between the ability to select your directory and declaring a directory name (at least I think it's a conflict).


i was following what Saulgoode said, the path for the pattern should be in the gimp preference:

So the first path for pattern in the gimp preference will be always the same ,will never give errors because there are all the default pattern so may be declared as default
but if the user prefer may declare something else.

Only problem i may image is that the default path is different in Windows and in Linux
(at least the absolute paths...maybe the relative paths are not different, not sure here )

but this is a problem only if the path should be written by the user...if could be chosen from the list of the paths in in Preferences/folder/pattern then will be no problem

But i don't know if a gimp script may access to that list

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:08 pm

I don't know if it can access a list, either. But saulgoode did offer to help with randomization of patterns.

Right now the script is telling me: Error: eval: unbound variable: inPatternDirectory with all his recommendations implemented. Menu pops ok, everything looks good til you try to run any option, doesn't matter which option you choose, same error.

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:20 pm

ah
i fear i can't help for that but if you post the script as it is now...well more chances to get help
(hem...i am very tempted to make blind guess but i try to resist to the tentation..)

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:32 pm

The coder? Hahaha... I already admitted I was in over my head, I'm just remaining determined. :)

And no, I didn't take offense to your earlier comment. I was trying to sort out any possible confusion before it even exists. I have Project Manager mentality. :gah!

Saulgoode used string-append:

(patterns (cadr (file-glob (string-append inPatternDirectory DIR-SEPARATOR "*.pat"))))

I got to thinking maybe it needs to be defined. When I add it to define, it then declares the new error:

Error while executing script_fu_MultiFill:

Error: string-append: argument 1 must be: string (so I think by adding it to the define list, broke the string). I have no idea how to define, so I am searching for similar scripts.

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:45 pm

mahvin wrote:Right now the script is telling me: Error: eval: unbound variable: inPatternDirectory with all his recommendations implemented. Menu pops ok, everything looks good til you try to run any option, doesn't matter which option you choose, same error.

The 'inPatternDirectory' variable needs to be added as a parameter to the main 'script_fu_MultiFill' definition such that it is associated with the corresponding widget (SF-DIRNAME) created in the registration procedure.

Re: Multi-Fill Script Help

Sun Feb 27, 2011 10:53 pm

When I do that, it gives the string error I mentioned above.
Post a reply