Gimp-Forum.net

Full Version: Blur, change mode, save as
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

I have a process that I need to perform multiple times in the future, so I started looking into the Script-fu documentation and tutorial on gimp.org. I can sort of follow the explanations and if I would keep at it for a day or so I might be able to get somewhere. (Edit: Actually, I'm not sure if I could manage it).

I decided to turn to this forum and ask the open question whether anybody (who is obviously infinitely more experienced  Smile ) is willing to get me going with a basic script. You can take this question two ways:
Arrow He's just being a lazy bum and let us do the work... (Please then let me know if a question like this is 'not done').
Arrow Oh, that's easy, I'll put something simple down, then he can take it from there and tweak and learn Script-fu...

My objective is to create an image in 5 shades out of a black and white picture. But before turning it into the shades, it needs to be Gaussian blurred to an X amount. The amout of blur depends on the picture. So the solution is trial and error. I do GB 10, 15, 20, 25, 30. Then I look at the results to select the best one.

Imagine the base-image is opened. The repetitive actions then are:
- Blur picture Gaussian blur 10;
- Image > Mode > Indexed 5, optimal palet, max colours 5;
- Save as pic10.jpg Same folder No compression;
- Undo;
- Undo;
- Blur picture Gaussian blur 15...
and so on.

Is there someone out there willing to give it a shot? I will also continue reading/working on it.

Thanks!  Shy Thomas.

PS. I'm using GIMP 2.10.22.

An overview of the work and that I can come up with myself.

The first step would be to set a Range of variables for the blur. Like {10, 15, 20, 25, 30}. I have no idea how to do that.

Then the first of the Range is loaded into variables 'X-value' and 'Y-value'. I have no idea how to do that.

Start logging steps to undo into a group. This is what I found to record the two steps thereafter into a group:
(gimp-image-undo-group-start image?)

Then comes the Blur script step. That I found:
(plug-in-gauss run-mode image drawable horizontal vertical method)
(plug-in-gauss 1 image? drawable? X-value Y-value 1)

Then comes the change image mode. That I found too:
(gimp-image-convert-indexed image dither-type palette-type num-cols alpha-dither remove-unused palette)
(gimp-image-convert-indexed image? 0 0 5 TRUE TRUE ignored?)

Stop logging undo steps.
(gimp-image-undo-group-end image?)

Next is Save as.
(file-jpeg-save run-mode image drawable filename raw-filename quality smoothing optimize progressive comment subsmp baseline restart dct)
(file-jpeg-save 1 image? drawable? Pic+X-value+.jpg Pic+X-value+.jpg 1 0 0 0 no_comment 4 0 0 dct?)

The script step to perform an the undo group. I couldn't find.
Something like (gimp-image-undo-now! image?)

Or maybe Undo-group-start and end are not needed, because at this point one can just do Gimp-Undo twice. But I can't find Gimp-Undo.

Increase variables 'x-value' and 'y-value' to next in Range. I have no idea how to do that.

Exit if Range is finished. I have no idea how to do that.

Run from the top. I have no idea how to do that.
For what you want to do, typically you don't "undo". You duplicate the starting image (once for each blur level) and apply your changes to the copy then throw away the copy after you have exported it. This is much faster because since the copy is throw-away, you can totally disable undo on it.

And undo-group-{start/end} don't enable the undo, they just lump whatever happens between the two as one undo step in the UI, so typically you bracket all the code of your script with them, and the user can undo your script with one Ctrl-Z, instead of one Ctrl-Z per change done in your code...

Do you really need the image to be indexed or do you just want 5 levels of gray? Because if you use auto-indexing, 1) you get a different color map for each image, which can be a problem down the line and 2) you aren't even sure that you get exactly the same result each time (since there is a bit of randomness involved). if you just want 5 levels of gray you can use gimp-drawable-posterize (see Colors ➤ Posterize in the UI).

Given the questions that you are asking you have not written much code before?

Do you know you can also write the scripts in Python, which is a much simpler language?
Hi Ofnuts,

Thanks!
- Clear. Duplicate it 5 times. Then work on each image.
- Colors > Posterize. Works fine too! I simply hadn't discovered it yet.

- Coding, I think I gave it like, I dunno, 40 hours of attampts. Mainly Python. I managed to build a Telegram-bot once that said Hi back, when you talked to it. But I found the learning curve steep.
- Scripting, I know FileMaker Pro beyond a beginners level. But that is a very closed garden.

This morning I saw the choice between Python-Fu and Script-Fu, so I thought as I know a bit of scripting, that is probably easier than Python that I found hard. But I'm open to the easiest option of course!

In any case, functionality-wise, I now have:
  • Define Range of variables for the blur. Like {10, 15, 20, 25, 30}
  • Load the first of the Range is loaded into variables 'X-value' and 'Y-value'.
  • Start loop
  •   Select 1st duplicate
  •   Duplicate image 5 times
  •   Blur
  •   Posterize
  •   Save as
  •   Close image
  •   Select next duplicate
  •   Increase variables 'x-value' and 'y-value' to next in Range
  •   Exit if Range is finished
  • Loop back
Now time for lunch Wink , then I'll look into what python-fu looks like.
In modern programming languages looping is simple

Code:
for blur in [10,20,30,40]:
   outputFile="%s-%02d.png" % (rootName,blur) # Possibly a bit more complex than this
   blurImage=image.duplicate() # Temporary copy
    pdb.gimp_image_undo_disable(blurImage) # Disable undo
   layer=blurImage.activeLayer
   pdb.plug_in_gauss_iir(blurImage, layer, blur, True,True)
   pdb.gimp_drawable_posterize(layer,5)
   pdb.file_png_save_defaults(image, layer, outputFile, outputFile) # Other calls possible with more options
   gimp.delete(blurImage) # Throw away this copy
Thanks Ofnuts!

But this is tough. I've been at it for hours, but I can't get the script to appear in one of the menu's, (let alone try it).

I do see it pass by in the splash-screen, so the folder where I placed the script.py is correct
Also I see a terminal screen flash by, so I think the Hello, world! is working.

From different sources I put this together:

Code:
from gimpfu import *

def plugin_main(timg, tdrawable):
    print "Hello, world!"

register(
    "tkemmere_blur",
    "Blur en 5 tinten maken en dat 5x met verschillende blur",
    "Blur en 5 tinten maken en dat 5x met verschillende blur",
    "tkemmere",
    "tkemmere",
    "21-11-2022",
    "<Image>/Filters/tkemmere blur",
    "RGB*, GRAY*",
    [],
    [],
    tkemmere_blur)

main()

for blur in [10,20,30,40]:
   outputFile="%s-%02d.png" % (rootName,blur)    # Possibly a bit more complex than this
   blurImage=image.duplicate()                    # Temporary copy
   pdb.gimp_image_undo_disable(blurImage)        # Disable undo
   layer=blurImage.activeLayer
   pdb.plug_in_gauss_iir(blurImage, layer, blur, True,True)
   pdb.gimp_drawable_posterize(layer,5)
   pdb.file_png_save_defaults(image, layer, outputFile, outputFile) # Other calls possible with more options
   gimp.delete(blurImage)                         # Throw away this copy

I'm not sure if everything is required. But this tutorial was quite explicit that it is the bare minimum.

I'm trying to make it appear in a menu, so I can start working with/on the actual script.

When I paste it in the console there are no errors, but nothing happens. Unless it is working without actually visually showing what it is doing and then saving the file in a place I'm overlooking. I don't know where rootName is. I did look in the most obvious places around my machine.

Is it normal that when a script is running you don't see anything happen?

Am I close?!  Smile  Thanks to anyone in advance!
Plenty of problems...
  • SyntaxError: Non-ASCII character '\xc2' in file Blur.py on line 4, but no encoding declared;: Many of your lines start with "non-breaking spaces" (0xA0, or 0xC2A0 once encoded in UTF8), so likely you are using a word processor to write your code  and it tries to "help" by putting non-breaking spaces where you put spaces. Change for a real editor (Notepad++ is free) that won't try to outguess you.
  • The last argument of your register() call is tkemmere_blur. This is supposed to be the name of a function, but this function is defined nowhere. I suggest you rename the plugin_main function to tkemmere_blur.
  • The plugin_main/tkemmere_blur function takes two arguments, an image and a layer (and this is what your real function you take as a minimum). So your register() call should declare these argument, so that Gimp can call your function with the adequate arguments. In the code you copied, the first pair of brackets in register() likely contains a PF_IMAGE and a PF_DRAWABLE line, that should also be present in your register().
  • The code I provided is going to be part of the body of your tkemmere_blur function, and the variabe image in that code is the first parameter (timg) in your function  (so you have to change of of these names)
To debug a python script, see this tutorial: Debugging python-fu scripts in Windows
Quote:...Am I close?!    Thanks to anyone in advance!...

Probably not, Ofnuts is a professional, thinks, works, most efficient ways.

Me, I leaned a bit of FORTRAN 40-something years ago. Most of the things I need/want in Gimp are already done, no real need to delve into Gimp scripting. At least Python is reasonably understandable, script-fu is akin to Sanskrit.

Try and find some simple examples first, never mind the code, look at the relationship between the top "def" and the bottom "register" section to get something in a menu.

Then get your code between that. Just get something working. One line at a time if necessary. Starting Gimp from a terminal can show errors.

Need a loop, but can not get the loop to work ? Then work in a linear mode. Its not a program to control a ballistic missile, keep things simple as possible.

I got a little block of code to work for a blur of 5, copied and pasted and edited for 10. I will attach my effort, you might be able to use it, add your own sections for blur 15, 20, 30...editing each as appropriate. (2 lines one for the blur, one for the layer name)

Unzip, put in your Gimp user profile plug-ins.
Find it in the tools menu, It dumps your jpegs in ../User/'your-name' folder. Not very convenient, look for 2.jpg , 10.jpg

Tried in A Win10 (VM) Gimp 2.10.32

best of luck.
(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]Plenty of problems...

Ai-ai!  Wink Lets see how far I get.

(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]
  • SyntaxError: Non-ASCII character '\xc2' in file Blur.py on line 4, but no encoding declared;: Many of your lines start with "non-breaking spaces" (0xA0, or 0xC2A0 once encoded in UTF8), so likely you are using a word processor to write your code  and it tries to "help" by putting non-breaking spaces where you put spaces. Change for a real editor (Notepad++ is free) that won't try to outguess you.

Indeed I started the script in Windows notepad, but soon switched to Notepad++ as it gives better overview.
I fixed the spaces. I used the [TAB] key for the indents, and I went over all hard-returns.
In Notepad++ ofcourse. Language is set to Python.

(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]
  • The last argument of your register() call is tkemmere_blur. This is supposed to be the name of a function, but this function is defined nowhere. I suggest you rename the plugin_main function to tkemmere_blur.

Done! Thanks!

(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]
  • The plugin_main/tkemmere_blur function takes two arguments, an image and a layer (and this is what your real function you take as a minimum). So your register() call should declare these argument, so that Gimp can call your function with the adequate arguments. In the code you copied, the first pair of brackets in register() likely contains a PF_IMAGE and a PF_DRAWABLE line, that should also be present in your register().

The source where I got my 'register()' example from didn't have PF_IMAGE nor a PF_DRAWABLE line. I looked up how to include them but Register() takes the following parameters acciring to help.register in the console: (proc_name, blurb, help, author, copyright, date, label, imagetypes, params, results, function, menu=None, domain=None, on_query=None, on_run=None). I'm not using the last 4. But I don't understand how I declare PF_IMAGE and PF_DRAWABLE in my register().

(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]
  • The code I provided is going to be part of the body of your tkemmere_blur function, and the variabe image in that code is the first parameter (timg) in your function  (so you have to change of of these names)

I adjusted the first parameter in the def tkemmere_blur() into 'image'. And the second to 'layer'.

(11-21-2022, 11:42 PM)Ofnuts Wrote: [ -> ]To debug a python script, see this tutorial:  Debugging python-fu scripts in Windows

Thank you, I ran the code in the Python-fu console. Bit by bit.
  • It crashes at "main()". I don't know the point of this line.
  • It also says rootName should be defined. Should that be a path to a file location?
  • Otherwise no errors.
And the result for now:
Code:
from gimpfu import *

def tkemmere_blur(image, layer):
    print "Hello, world!"
    
register(
    "tkemmere_blur",
    "Blur en 5 tinten maken en dat 5x met verschillende blur",
    "Blur en 5 tinten maken en dat 5x met verschillende blur",
    "tkemmere",
    "tkemmere",
    "21-11-2022",
    "<Image>/Filters/tkemmere blur",
    "RGB*, GRAY*",
    [],
    [],
    tkemmere_blur)    # How to declare image and layer in this register function?
    
main()

def rootName("T:/files") # Should rootName be a path?

for blur in [10,20,30,40]:
    outputFile="%s-%02d.png" % (rootName,blur)    # Possibly a bit more complex than this
    blurImage=image.duplicate()            # Temporary copy
    pdb.gimp_image_undo_disable(blurImage)        # Disable undo
    layer=blurImage.activeLayer
    pdb.plug_in_gauss_iir(blurImage, layer, blur, True,True)
    pdb.gimp_drawable_posterize(layer,5)
    pdb.file_png_save_defaults(image, layer, outputFile, outputFile) # Other calls possible with more options
    gimp.delete(blurImage)                         # Throw away this copy

If I understand correctly, due to the lack of declaring image and layer in the register function, Unfortunately it doesn't yet appear in the Filters menu.

Now I will dive into what @Rich2005 wrote. Not sure whether I manage to respond, it is late now and tomorrow is a day with a full schedule that unfortunately leaves me no Gimp/Py time.

Thanks @Ofnuts!

(11-22-2022, 01:30 PM)rich2005 Wrote: [ -> ]
Quote:A ...Python is reasonably understandable, script-fu akin to Sanskrit...

B ...Try and find some simple examples first, never mind the code... ...get your code between that...

C ...work in a linear mode...

Hi Rich2005,

Thanks to you as well!

A. Yes, I went the Python way now. Not thinking of turning back reading the Sanskrit metaphore!  Confused
B. I got your script running, in the Tools menu, so that will do, to elaborate on!  Smile
C. Your script is written lineair. Copy pasting a couple of lines is no problem of course, but automating it into a loop is of course more fun and elegant.  Wink

I ran the script from the Tools menu and it is working here too! It can't save, a permission thing, I'll look into that later. I really need to sleep now.

Thanks! Forums are great! I'm afraid I can't do much back on this one, but I can mention that on the FileMaker Pro forum I also do help people out.

Will be back.  Smile
Cheers, Thomas.
Hi all,

Following-up. I got back at it.

Tried to get Ofnuts script to register as well. But I noticed when I changed something in Rich2005's script in the body (Like a \ instead of a / in the path to the file to save), Rich's script doesn't register either any more. Conclusion: I probably have all the register() items in Ofnuts script correct, but there is something wrong in the body of that script. Ofnuts, you pointed to the debug page, I didn't get to it yet.

Rich's script, I straightened out, renamed things here and there, and it is now doing blur 10, 20, 30, 40 and 50. Also, it is saving in a particular place on my file-server.

I have reached my objective!  Smile

I now also have the knowledge to make a similar script that can create different levels of contrast, A, B and C. That also has an effect on how the borders between the 5 colours run, which is what I'm interested in.

And when I combine those, I will have a sort of a matrix in files: 10A, 10B, 10C, 20A, 20B, 20C, 30A, 30B, 30C, 40A, 40B, 40C, 50A, 50B and 50C.

Lots of thanks to @Ofnuts and @Rich2005!
Cheers, Thomas.