This script-fu for The Gimp is a attempt to simulate a vintage look.
For Examples see http://www.mmip.net/gimp-script-fu
This Script is based on the deviantart tutorial from CrazyMurdock1 (Vintage look in Gimp)
Optional sharpness and contrast layer
Version 0.2 - Optional sharpness and contrast layer
thanks to elsamuko (http://sites.google.com/site/elsamuko/gimp)
Version 0.3 - Move to Filters -> Artistic, changes in Bleach Bypass
| Attachment | Size |
|---|---|
| vintage-look_0.1.scm | 2.55 KB |
| vintage-look.0.2.scm | 4.58 KB |
| mm1-vintage-look.0.3.scm | 4.18 KB |
Comments
love it!
thanks - I've been using it a lot!
Batch call of this script
Hello, I'm running my own script by command:
gimp --console-messages --no-data --no-interface -b '(once-vintage-look "test.jpg")' -b '(gimp-quit 0)'
and receive this message:
batch command: executed successfully.
but image has only new time stamp, but not edited. Please help me with batch processing of my images using this script. Thanks.
This is my own script:
(define (once-vintage-look filename)
(let*
((image(car(gimp-file-load RUN-NONINTERACTIVE filename filename)))
(drawable (car (gimp-image-get-active-layer image)))
(mm1-vintage-look RUN-NONINTERACTIVE image drawable 17 20 59 TRUE)
)
(gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
(gimp-image-delete image)
)
)
Regards
Ilja
Merge before save
You need to merge the layers before saving, else only the original layer will be saved.
Add these lines to the end of the script:
)
(gimp-image-merge-visible-layers image EXPAND-AS-NECESSARY)
(set! drawable (car (gimp-image-get-active-drawable image)))
(gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
(gimp-image-delete img)
)
)
gimp_file_save() is tricky about saving all layers
I will expound, since this has bitten me also.
gimp_file_save() saves a *drawable* not an *image*. You might expect it to save all layers (drawables) of the image, but it doesn't always. Exactly what parts and what format it saves depends on the extension (suffix) of the filename parameter. (If the extension is .xcf would it save all layers of the image?? I haven't tried that. If another format supports layers, like .xcf does, would it save all layers?) In other words, the image parameter is not used, since the drawable knows which image it is part of.
I have tried a call to gimp_file_save(aimage, adrawable,... ) where adrawable did not even belong to aimage, and it works, saving the drawable, without throwing an exception.
The Gimp Library documentation is not clear about this.
An aside, a followup about gimp_display_new():
See other parts of this thread.
The following code does work to keep a Python plugin from aborting if called NONINTERACTIVE with a call to gimp_display_new()
# Show the new image
try :
gimp.Display(new_image)
pdb.gimp_displays_flush()
except gimp.error:
pass # If runmode is NONINTERACTIVE, expect gimp_display_new() to fail
Another aside, about scripts returning values:
Scheme plugin scripts don't have return values. If a Scheme script creates a new image, there is no easy way to pass the new image to subsequent scripts (say in a larger script, or a batch command)???
In a Python plugin, you can declare return values in the registration call e.g. :
....[(PF_IMAGE, "new_image", "New image.")], ....
and return them:
return new_image
Or for example you can return a drawable that the plugin has created.
It doesn't seem like many plugins are returning values, somewhat limiting their use as NONINTERACTIVE commands.
Don't specify the run mode
When a Script-fu script calls another Script-fu procedure, you should not specify a 'run-mode'. So the short answer is to remove the "RUN-NONINTERACTIVE" from the following line of your code.
Going a little deeper, creating a Script-fu script typically entails two parts: 1) providing the Scheme definition for the function, and 2) registering the function with GIMP's Procedural DataBase.
PDB registration makes the script available to plug-ins and allows for the function to be added to GIMP's menus -- but PDB registration is not actually needed in order to make the function available within Script-fu (the function becomes available within Script-fu when it is defined).
Even though a function such as 'mm1-vintage-look' is registered with the PDB, within Script-fu the function appears as just a normal Scheme definition. When the function is invoked within Script-fu, the PDB interface is ignored and there is no need to specify a run-mode. (When plug-ins invoke the function, they do so through the PDB and the plug-in specifies a run-mode to the Script-fu interpreter.)
The reason that no error was generated when you ran your batch is owing to happenstance in the values used for 'image' and 'drawable' identification. When you first open GIMP both image and drawable IDs get uniquely defined starting at "1" and increasing. In addition, the constant RUN-NONINTERACTIVE is pre-defined as "1" (RUN-INTERACTIVE is "0").
Therefore, when you invoke 'mm1-vintage-look'
with the arguments:
the arguments passed to the function are:
of which the first two arguments ("1 1") are treated as the image and drawable respectively. While the first (only) layer in your newly-opened image has an ID of "2", there is indeed a "drawable" that has an ID of "1" -- i.e., the image's selection.
The net effect is that your batch process is running the Vintage filter on the selection (with CMY values of [2 17 20]), but the layer itself is unchanged.
batch run-mode scheme python calling scripts from scripts
You can pass run-mode to another script by calling (gimp-proc-db-call...) instead of the script itself.
I can't find any way to determine the run-mode in a Scheme script? So how can you avoid calls that require interaction such as gimp-display-new() ?
Its different in Python plugins: run_mode is an optional keyword parameter that you can pass and refer to. It is still hidden from view most of the time, but its there if you need it. Also, a call to another plugin DOES go through the PDB, and since you can't import another plugin, you can't call it directly.
The way run-mode and inter plugin calls are implemented IS very confusing and not consistent among C, Scheme, and Python plugins.
(I had a longer post but the spam filter prevented it.)
> I can't find any way to
> I can't find any way to determine the run-mode in a Scheme script?
By the time your Script-fu code starts executing, all interaction has already completed (if the script was run interactively, the dialog appeared, the user changed the settings, the dialog was closed, and your script called with the chosen values). As far as your script is concerned, it is running non-interactively.
> So how can you avoid calls that require interaction such as gimp-display-new() ?
I don't know if that can be done (I've encountered this problem before when running scripts from the console). Will investigate. To my knowledge, 'gimp-display-new' is the only PDB function which is problematic in this sense.
If you want to run a plug-in (which accepts a run-mode) interactively then the best way to do so is to pass the SF-RUN-MODE "constant" to the plug-in: "(plug-in-gauss SF-RUN-MODE image drawable 5 5 RLE)".
What SF-RUN-MODE does is pass the run-mode with which your script was initially invoked to the plug-in. The reason using SF-RUN-MODE is better than using RUN-INTERACTIVE is because your script can then be used non-interactively (by other scripts or plug-ins).
EDIT: combining the above two concepts, a plug-in could be written which only accepts 'run-mode' and only opens a new display if it is called interactively. This is something of an abuse of the 'run-mode' argument but maybe if the plug-in and its argument were named properly this wouldn't be a problem.
Plug-in's RUN function (incomplete):
run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { GimpRunMode run_mode; run_mode = param[0].data.d_int32; if (run_mode != GIMP_RUN_NONINTERACTIVE) gimp_display_new(); /* return a status */ ...Script-fu invocation (assuming the plug-in is registered as 'safe_display_new'):
SF-RUN-MODE
I accept your explanation that Script-fu does all the user interaction (if there is any) before the script main() runs.
What I am doing is calling a Scheme script from another Python script and explicitly passing run_mode = RUN_NONINTERACTIVE. And a call in the Scheme script to gimp_display_new() fails. In that case, the script IS running noninteractive, hence impossible to new display.
I think this is another case where the punishment doesn't fit the crime: gimp_display_new should return success in this case and NOT abort the script. One way of looking at it is: if the script is running non-interactively, then gimp_display_new creates a None display. Maybe that can't be done because you can't pass a None display to any other Gimp procedures that take a display?
> pass the SF-RUN-MODE "constant" to the plug-in: "(plug-in-gauss SF-RUN-MODE image drawable 5 5 RLE)"
That is interesting because the earlier discussion said you CAN'T pass a run_mode parameter to a script!! Now you seem to say there is a magical "constant" that you CAN pass to a script. You quote "constant" because it has a different value depending on the current run-mode (so it's not constant in the sense of always having the same value.) Why wouldn't SF-RUN-MODE be taken as the image parameter, as explained earlier? It seems like more magic.
And if SF-RUN-MODE is a pseudo-constant, can you use:
(equals SF-RUN-MODE RUN-NONINTERACTIVE)
to determine the current run mode? (I should test that myself.)
To be clear, you are suggesting that someone should write a C plugin, that you call safe-display-new that returns True if the current run mode is RUN_INTERACTIVE .
Then, in a scheme script, if you want to avoid calling gimp-display-new if the run-mode is interactive (sorry, I am not fluent in Scheme):
if (safe-display-new SF-RUN-MODE) : # if RUN_INTERACTIVE
gimp-display-new()
A web search reveals that SF-RUN-MODE is fairly new (2007) and seems rather undocumented.
SF-RUN-MODE
> What I am doing is calling a Scheme script
> from another Python script and explicitly
> passing run_mode = RUN_NONINTERACTIVE.
> And a call in the Scheme script to
> gimp_display_new() fails.
Are you running on a headless server? My recollection is that doing a 'gimp-display-new' *on a machine that has a GUI interface* results in new display window, even though the script is being run non-interactively. In other words, I wonder if the failure you are experiencing is an actual "system" error when GIMP attempts to create the dialog window (and not that GIMP is refusing to create the dialog).
If the failure is owing to a system error, you should be able to ignore it in your script by wrapping the 'gimp-display-new' call in a catch/throw block. This would allow Script-fu to run your script non-interactively on headless machines, however, should you have a GUI interface then the new display will be created on it.
> That is interesting because the earlier
> discussion said you CAN'T pass a
> run_mode parameter to a script!!
> Now you seem to say there is a
> magical "constant" that you CAN
> pass to a script.
I'll try to clarify. When a script is executed via the PDB (e.g., it is being called from a Python plug-in), it is not invoked directly. Instead, the Python plug-in calls (via the PDB) a Script-fu invoker function which is passed the name of the script plus all of the PDB arguments (including the run-mode).
The Script-fu invoker function ('script_fu_script_proc()') tests the run-mode and if RUN-NONINTERACTIVE, runs the script with the arguments specified by the Python plug-in -- except the run-mode, which is not passed as an argument to the script (but it does set the SF-RUN-MODE constant).
If the run-mode passed to the Script-fu invoker is RUN-INTERACTIVE then the arguments supplied by the Python plug-in are ignored, and an interactive dialog is created to obtain the values of the arguments with which to run the script. Once the dialog has been closed, the Script-fu invoker runs the script (non-interactively) with the arguments that were specified in the dialog.
As a final (side) note, whenever a Script-fu script is invoked from another Script-fu script, the PDB invoker is bypassed altogether and the script run directly (and no run-mode should be supplied).
> You quote "constant" because it has a
> different value depending on the
> current run-mode (so it's not constant
> in the sense of always having the same
> value.)
Well, it's a constant in the sense that the script can't change its value. It might have been more intuitive to have implemented it as Scheme function (but that too would be somewhat odd).
> And if SF-RUN-MODE is a pseudo-constant,
> can you use: (equals SF-RUN-MODE
> RUN-NONINTERACTIVE)
> to determine the current run mode?
> (I should test that myself.)
After further testing, it appears this is possible. Sorry for having stated otherwise.
SF-RUN-MODE
Thanks, this is educational.
Re headless: No, I am running a typical Ubuntu PC/workstation. I will have to test again to make sure that it was gimp_display_new that failed when run mode was NONINTERACTIVE. Probably I just assumed that was what failed.
Re (plug-in-gauss SF-RUN-MODE image drawable 5 5 RLE)": You seem to be saying that from a Scheme script, you CAN pass a run mode to another Scheme plugin in this fashion, whereas previously I thought you said you CANT and that the first parameter would be perceived as the image parameter. I understand your explanation of Python calling Scheme script. Its not important to me, as I won't be using Scheme to call Scheme.
My conclusion is that in order for scripts to be called with run_mode NONINTERACTIVE, the onus is on the author to insure that is possible, for example by not calling obviously GUI related functions like gimp_display_new.
I was trying to automate the testing of certain plugins by calling them noninteractively from a Python harness. I will have to rewrite some of the plugins. But now I know how to find out in Scheme whether the run_mode is NONINTERACTIVE.
Scripts vs Plug-ins
> You seem to be saying that from a
> Scheme script, you CAN pass a run
> mode to another Scheme plugin in
> this fashion, whereas previously I
> thought you said you CANT ...
I do not consider Script-fus to be plug-ins (they are scripts). By the same token, filters written in C, Python, Perl, etc are all plug-ins (they are external executables that are placed in GIMP's plug-ins folder). A Python plug-in might be considered a "script" from the command line's point of view, but to the GIMP it is just an executable program (which invokes the Python interpreter and interfaces with libgimp).
When a script calls a plug-in, it needs to provide a run-mode as the first argument. When a script calls a script, it should not provide a run-mode (the run-mode of the called script is always RUN-NONINTERACTIVE).
A script can never invoke another script interactively. A script can invoke a plug-in interactively (e.g., call 'plug-in-gauss' and the Gaussian blur dialog will appear); but not another script (your script can't call 'script-fu-drop-shadow' so that the Drop Shadow dialog will appear).
> and that the first parameter would
> be perceived as the image parameter.
Basically, yes. Though not necessarily an image, but the first specified "SF-parameter" (SF-DISPLAY, SF-IMAGE, SF-DRAWABLE, SF-LAYER, SF-CHANNEL, SF-VECTORS, ...).
> My conclusion is that in order for
> scripts to be called with run_mode
> NONINTERACTIVE, the onus is on
> the author to insure that is possible,
> for example by not calling obviously
> GUI related functions like
> gimp_display_new.
I believe 'gimp-display-new' is the only PDB function that does not accept a run-mode yet still results in a GUI window being created. None of the other PDB functions create a dialog (or other window) except for the plug-ins and scripts (all which accept a run-mode argument when called via the PDB).
expand on that
To expand on that, When you use script-fu there IS a plugin running. That is the script-fu interpreter.
This interpreter then runs scripts.
-Rob A.
Re: Scripts vs Plug-ins
I've been following this conversation with much interest, and curiosity got the better of me. You said:
"A script can never invoke another script interactively."
I'm curious as to why this is the case. Is it because no two scripts can be active at the same time due to scheme's structure? Is it a permission issue within GIMP's code, itself? What separates this ability between scripts and plug-ins? Not sure if I am asking this in the right way. Hopefully, you'll have an idea of what I am trying to get at.
> I'm curious as to why this
> I'm curious as to why this is the
> case. Is it because no two scripts
> can be active at the same time
> due to scheme's structure?
This limitation is not owing to Scheme itself, nor the Script-fu interpreter, but with the way the Script-fu invoking code was originally written. To change this behavior, it would not only be necessary to re-write the dialog generating and PDB interface code, but all scripts calling 'script-fu-*' functions would need to be modified to add the run-mode.
scripts
It doesn't appear.
It doesn't appear in my Gimp also.
Did the same as this dude. But it wouldn't appear in Gimp. I'm usin Vista. Thanx.
Error while executing
I got the same error
I got the same error message...any ideas? how do I fix this?
Works for me. Without any