GNOME Bugzilla – Bug 51937
Script recorder (a.k.a. macro recorder)
Last modified: 2016-06-03 12:56:11 UTC
I wish the Gimp would include some kind of "recorder" of actions that
could save it in script-fu form, allowing people like me (non programmer)
to easily automate some tasks.
This feature is on the TODO list, but several important changes are
necessary before it can be implemented. The user interface must be
separated from the core, and all actions performed via the GUI must
result in corresponding PDB calls. Once this is done, then all
actions invoked through the menus, all brush strokes, selections and
other actions will go through the PDB where they can be caught and
recorded in a file. Then it should be easy to export the sequence
of actions as a Script-Fu or Perl-Fu script.
This feature will probably be implemented in Gimp 2.0.
Re-assigning all Gimp bugs to default component owner (Gimp bugs list)
Reassigned to current CVS because it's a wishlist item.
For the record, I started working on a script recorder but a hard disk
crash has destroyed most of my code. I will try to work on it again
as soon as my new PC is ready and I can get CVS access again.
Hmmm... Six months have passed and I still haven't bought my new PC.
But I will get it Real Soon Now and the macro recorder is definitely
on my TODO list...
Attached you'll find a patch against Gimp 1.2.cvs which
implements some basics I've written some time ago to
get macro recording. It isn't meant to be applied to
the stable branch but mostly to get some disscusion on
The main issue not yet resolved is the disability to get
on the parameters of plug-ins run interactively. AFAICS
to get those parameters some addition to the plug-in protocol
would be needed, i.e. gimp_set_last_values() called by any
Maybe these additions should be combined with some general
PDB extensions like default parameters (see bug #71200) ?
Created attachment 12796 [details] [review]
The patch mentioned above. The incomplete recorder plug-in is missing.
Thanks for the interesting patch. As you wrote, that could be an
interesting starting point for discussion and for developing that
feature in a more correct way.
You mention some API changes for the plug-ins. Note that several
things will have to be changed in the way the plug-ins are
communicating with the core:
- Bug #71200 (named parameters) is not very urgent IMHO but would be
nice to have. So I don't know if this will be done for 1.4 or 2.0.
- Bug #81636 ("Repeat Last" vs. "Re-Show Last") is about having two
sets of "last values" instead of one: one for "Repeat Last" and one
for "Re-Show Last".
- Bug #63610 (plug-in settings persistent accross sessions) is about
adding an easy way for the plug-ins to save some of their settings
(via the core, not on their own) so that they can be re-used even
after closing and re-starting the GIMP.
- Bug #62988 (Export dialog must be treated as transient) requires
the core to pass the window id of the save dialog to all file
plug-ins (at least under X11). This is another API change.
In addition, other API changes will be needed before 2.0 so that new
channel types can be supported. Anyway, this short list shows that
several changes will be needed soon. Regarding the ability to get
the values from the plug-ins that are run interactively, most of them
already call "gimp_set_data()" to store their values. We just have
to find a way to ensure that the data can be read and understood by
the core so that it can be used by the recording function.
If I understand gimp_set_data() correctly it simply
allows to store and later retrieve via gimp_get_data()
some arbitrary data only known to the plug-in.
But for macro recording it needs to be 'typed' data,
having something like :
gimp_done_procedure (gchar *name, /* procedure name */
...); /* Types and data as in
* gimp_run_procedure(), here set interactively,
* but needed to run the procedure with the same
* results non-interactive */
in _every_ plug-in would be nice. The data returned from the
plug-in after a successful interactive call could than probably
be used to resolve bug #81636 and #63610 with only very little
To give you an impression how far this could work here's some
dummy output of a very simple macro recorder based on the above.
It is create by a small Python script attached below. IMO there should
not be one macro recorder but as much macro recorders as there are
language bindings. For me the PyGimp recorder would be the most
interesting, but the same infrastructure obviously could be used for
other scripting languages. And the recorder obviously does not need
to be implemented in its output language - although this helps if
it's a nice language :-)
Created attachment 12800 [details]
the test script for the above (not yet a real recorder)
Yes, I know that the data that is saved by the plug-in must be
'typed', that's why I wrote that we "have to find a way to ensure
that the data can be read and understood by the core". Of course,
this will require some changes to the gimp_set_data() function so
that the type of the arguments can be passed as well, instead of only
passing an untyped block of data. So the function cannot be used in
the same way as it is used currently. But I mentioned it because I
think that it is better to change this function instead of adding a
new function. If we keep the old function, then it is likely that
some plug-ins would not be updated and nobody would understand why
they cannot be used by the macro recorder. If we break the prototype
of the old function, then we are sure that all plug-ins will have to
be updated, otherwise they would not compile. Maybe this is a the
'fascist' way of doing it, but this is probably the best way to
ensure that we have a consistent system after the API change.
By the way, in addition to the type of the parameters, it would be
important in some cases to know their meaning. For example, the
paint tools can generate a list of points for the stroke. These are
X and Y coordinates for the points. If we want the macro recorder
to be able to repeat these operations on an image of a different size
and give the choice of re-centering the brush strokes or scaling them
to the size of the new image, then it has to know that these values
are X and Y coordinates. So we need to be able to associate some
semantic information to some of the PDB parameters. Maybe this can
be done by having more than one type of integers or floats. I am not
sure yet about what is the best solution for that.
Regarding the multiple languages, I don't think that we should have
multiple macro recorders. From my point of view, the macro recorder
is a core function that is language-agnostic: the only thing that it
does is to record the list of PDB calls and their parameters. It
should also provide a simple user interface for starting/stopping
the macro recording. When the user stops recording and chooses to
save the script, he/she is asked if the sequence of PDB calls should
be translated to Script-Fu, Python, Perl or any other language.
This last part could be done by a plug-in (so that we can add more
language outputs easily), although it could also be done by the core.
IMHO redefining the meaning of gimp_set_data() wouldn't enforce
consistency but simply increase the burden to get a first working
prototype. There still are many plug-ins which don't use it.
Using my approach the macro recorder would have a simple way to tell
why it didn't fully record a macro call, it would simply not see
the closing bracket. And could either decide to run the respective
plug-in interactive again or maybe fill in default values.
There are sure more demands than simply recording plug-in
invokations (tool strokes, modifying display setting e.g. zooming
and scrolling, window movements, ...) but are these really
necessary for the first version ? I think not; instead they
would again make a first working and useful prototype more
unlikely to happen.
To me it looks very reasonable to at least write the Python output
plug-in in Python. If the start and stop recording function
belong into the core or into different plug-ins doesn't matter
that much, but what's the purpose of recording a Python plug-in
if you not even have Python installed (the same holds true for
Perl, which e.g. isn't available for win32) ?
Maintaining the language output needs to be done in context of
the language bindings anyway.
Regarding your first point, we could try another way: instead of
redefining gimp_set_data(), we define a new function that takes a
better list or arguments but serves the same purpose so that it can
replace gimp_set_data() in all plug-ins that are updated. Then we
declare gimp_set_data() as deprecated but leave it in the code for a
while during the 1.3.x or 1.9.x phases (the function would generate
a warning every time it is used). This would give some time to adapt
all plug-ins, while still allowing a smooth transition. The obsolete
function would then be removed when the next major stable version of
the GIMP is released.
About the brush strokes and other operations: this is precisely what
I was working on when my hard disk crashed. :-( Implementing some
basic recording of these actions is not as hard as you think. It
requires some work, but I think that it would be very useful in the
macro recorder. Note that I never intended to record the operations
that are not affecting the undo stack, such as zooming in/out or
moving the windows. This is something that could be done with GERD
(see bug #82648) but is probably out of scope for a simple macro
About the multiple language bindings: I would like the interface to
the recorder to be the same, regardless of what language is
installed. This will ensure that there is only one way to start and
stop recording. This will make documentations and tutorials easier
to write and maintain. That's why I would like this to be part of
the core and language-independent.
For the language outputs, I am not sure that it would be stupid to
allow the user to generate a script in a language that is not
installed in his/her copy of the GIMP. It would be nice to allow the
users to generate and distribute a script in several languages, so
that others can download the version they prefer. So a Windows user
could generate a Perl script to be used by those who prefer Perl, or
generate a Python script for those who prefer Python, and so on. The
code for generating the Python output would be 90% similar to the one
for generating the Perl output (Script-Fu would be a bit more
different, but not that much).
Here are some additional comments about what I had started to
implement in May, before my hard disk crashed. Although I have lost
the code that I had started writing, I still have some notes that can
help me to re-create it. Here are some of them...
- A new GObject, GimpScriptRecorder (singleton) is referenced by a
global pointer (script_recorder). Most of the time, this pointer
is NULL. If it is not NULL, then the recorder is active and the
PDB calls should be logged.
- The script_recorder contains a glist of GimpScriptAction objects
and several variables used for housekeeping. Among these, one
variable pdb_call_depth is incremented every time a PDB call is
started and decremented when the call returns. If the PDB calls
a script, which in turn makes other PDB calls, then only the
first-level call will be recorded.
- The GimpScriptAction object contains simply the name of the PDB
function that was called, together with its parameters (I had not
finished that part yet).
- When the user stops recording, the user is asked in what language
the script should be created (translated from PDB calls) and where
the file should be saved. Maybe there should be an option to save
multiple scripts (multiple languages) from the same session?
Suggestions/comments/complaints are welcome. ;-) I hope that the
reporter (Pinet.Daniel@wanadoo.fr) is not bored by these comments.
I sure do hope that you folks will/are still considering this for Gimp 2.0. It would be
nice to even have it so that one could get the "basics" down and then edit the
script to fine tune things more. Paint Shop Pro 8 uses Python scripting and allows
you to record the scripts, then even edit them in a text editor by clicking a button
on the interface. This would be quite handy.
what I have in mind is to generate a list of PDB calls that can be saved
into different formats depending on the target language: Script-Fu
(Scheme), Perl, Python, etc. It would then be possible to edit the
script and to refine it according to what you want to do with it.
However, this feature will not be ready in time for 2.0, which will be
released soon. It depends on several other features that are not ready
yet (see bug #68281 and other potential dependencies in bug #101604). I
hope that I will find some time to work on it before the next major GIMP
release, as long as some of the dependencies are resolved.
Although it would only be a small part of what is required for script recording
it would be useful for script writers to be able to access/save the Undo History
and use it (and some trickery with gimp_pdb_query) to generate rough scripts and
work from there.
4 years and counting -- has the UI been separated from the core?
Hi, this Rec-implementation is the only big thing that i miss in the gimp!! I
would be veeeery happy, if this would be in future-versions a normal tool! How
long have I to wait?? And is there a more recent plug-in or patch then these
from dec. 2002?? greets. pat.
*** Bug 328222 has been marked as a duplicate of this bug. ***
It is likely that I will not have the time to work on this in the near
future, so any volunteers are more than welcome...
*** Bug 333562 has been marked as a duplicate of this bug. ***
What I intended by submitting Bug 333562 was something different than a script recorder. I assume the script recorder discussed in this bug (51937)was geared toward generating macros that could be executed to perform an action. I was just wanting a record of the actions that were performed, essentially a tool for logging workflow. It may or may not be the same tool discussed in this bug, depending upon how the macro recorder function is implemented.
It is the same tool. If we implement logging, we have effectively implemented a macro recorder.
Can you make gimp somehow dump the "echos" of commands given to it to the stdout? This would be a hack-around for those of us who have no idea about programming but can figure out a way to copy paste stdout output to a script file...
I mean, the scripting and its documentation is meaningless to any non-programmer... such stdoutput would at least let me look at what the "command" for my action within the gimp is and put it in a file as a script...
1. I launch gimp with
$ gimp -spit-everything-here-please
2. I do an action in gimp such as Layers > Colors > Hue-Saturation > increase saturation by 5 points > click ok
3. gimp kindly tells me that the meaning of that action is:
(blablabla arg1 arg2 arg3 ...)
4. I put that in a file, register it as a script, be happy.
This would hold us until someone has time to implement this would-be-perfect feature...
>This would hold us until someone has time to implement this would-be-perfect
What you've described has most of the same requirements as full macro recording. Only plugins are called through the PDB by the GIMP core, and your example is not a plugin call. Additionally to everything working through PDB... plugins themselves can make PDB calls, so tracking of the 'depth' of PDB calls is also necessary.
The only real differences between your suggestion and a script recorder are:
* A GUI for manipulating macros (maybe)
* A script recorder would also have to record usage of tools (pencil, move, crop, rotate..)
your suggestion may be useful, since IMO recording tool operation as pdb calls is one of the more difficult problems.
The suggestion has of course been brought up before and if it would be simple to implement, we would have a macro recorder by now. The problem is, as David already pointed out, that there is no central place where all commands would go through.
What about the UNDO? I've not found anything in the DB, but the UNDO-Journal shows all actions done to the image. Is'nt it the central place you looking for?
> What about the UNDO? I've not found anything in the DB, but the UNDO-Journal
> shows all actions done to the image.
Sorry to ask but, how do you access that? thanks :)
The undo journal does contain different versions of the image. It does not record how they have been created.
AFAIK the undo history is not accessible through the PDB yet (this has been suggested in comment #17). I'm not aware of plans about how to do this, and it should be handled in a new bug, too.
But please make sure that this is feasible first. You should write up a short proposal (how can it be accessed, what does happen if it is used, who will be using it, what for?, ...) and bring this up on the developers list.
I don't think that we will make the undo history accessible thorugh
the PDB, and it won't be used for any future macro recorder. It's rather
likely that the undo history is going to be reimplemented/replaced
completely as soon as GIMP has macro recording capabilities.
*** Bug 429331 has been marked as a duplicate of this bug. ***
I think this feature could be designed not to require a new central place for processing commands. Consider this design: When you begin "recording", a new window with a multi-line text-box appears. Every time you perform a command, the corresponding script-fu code is appended in the text-box. That's it. Benefits of this design include:
1- The script interpreter takes care of the "central place for processing commands".
2- Watching the script build itself would be useful for teaching people how to do scripting with the GIMP.
3- Implementation is simple. Each tool just needs to send a snip of script-fu to the macro window, which it will append to the script.
4- Each tool only needs to be aware of it's own script-fu command. No new command-executing abstraction needs to be designed.
5- It won't break existing tools. If some tools neglect to send a string to the macro window, then that command simply won't appear in the macro. This could be handled as a separate bug. As long as the major tools support the macro recorder, the feature is still very useful. You could call the tool a "script-building helper/hint tool" instead of a "macro recorder" during phase-in, so people don't expect every plug-in on the planet to support it already.
Perhaps we'll also want a more convenient way to execute the scripts too, but that can be designed later. Does it really need to be any more complicated than this?
You've contradicted yourself. You've said that this "could be designed not to require a new central place for processing commands" but then your first item says that the script interpreter is the central place for processing of commands.
The big job is not to make a place to process commands, but to wire up the large number of GIMP UI touch points to use it.
(In reply to comment #34)
> You've contradicted yourself. You've said that this "could be designed not to
> require a new central place for processing commands" but then your first item
> says that the script interpreter is the central place for processing of
> The big job is not to make a place to process commands, but to wire up the
> large number of GIMP UI touch points to use it.
Script processing already exists, so I think my item #1 is consistent with the statement that it does not require a "new central place for processing commands" (emphasis on the "new"). Also, the point of my item #5 was to suggest that this feature did not need to be implemented as one "big job", but that I thought it could be acceptable to wire up the touch points incrementally, as long as some care was taken about how the feature was presented.
But the script interpreter isn't currently a central place for processing commands. It could be, but hooking all the commands in is the big job.
As far as #5, you're completely glossing over the "some care was taken" bit, which is again the hard part of presenting a partial implementation that makes sense to a user.
So yosh, are you saying that a patch implementing, for example,
gimp-display-set-zoom, gimp-display-set-screen, gimp-display-revert-zoom, and gimp-display-fullscreen, gimp-display-get-shown, gimp-display-set-shown, gimp-display-set-snap, gimp-display-get-snap
would be a step in the right direction* and likely to be accepted if good quality?
* the right direction being, eliminating code duplication by making the GUI actions just call the PDB -- possibly through a specific action type.
I have previously avoided writing such patches because I got the impression that 'there are UI features that we don't want to expose on the PDB'. However, as far as I can see, we must expose all major UI features in order to approach implementing this.
(personally, I know I could use gimp-display-set-zoom, as I've often wanted to automatically create another view and set it's zoom to 300% for an accurate preview of the picture at target resolution; and being able to remove all 'extras' (don't show selection, rulers, guides, layer borders, statusbar, or menubar)
The rule is that the PDB doesn't have anything to do with the UI. I very much doubt that that people would want a macro recorder to record things like "Zooming in to 200%". Actually, I think as soon as non-destructive editing is in place and all actions are stored in the image itself and can be repeated and edited at any time, this request will become obsolete. So let's concentrate on that. We might want to close this report as WONTFIX.
> very much doubt that that people would want a macro recorder to
> record things like "Zooming in to 200%".
No, but I would like to record macros like "convert to grayscale, save", so
>close this report as WONTFIX.
I hope you are not serious, because lack of macros is serious limitation to Gimp (and a lot of other programs to be exact).
"Convert to greyscale, save." is perfectly well covered by what Sven described.
Anything which manipulates the image at all, really.
My use case, OTOH, is not. Currently, I have to resort to unportable (and i18n-unsafe) hacks involving xdotool in order to do this simple automation. I do agree it has little to do with macro recording (though I would be seriously surprised if someone who edits a lot of photos wouldn't benefit from the ability to toggle between two fixed zoom ratios, with no adjustment necessary.)
Macro recording is essential to any serious image editing.
The workflow is full of tedious tasks, like applying levels and contrast then autocrop all layers of scanned images. Without macros this takes forever, manually repeating every step. With macros just record what you want and hit a button for every image; enormous time-saver.
I recently put many hours into doing this task with the Gimp, seriously trying to use it in production but I had to give up and go back to that other image editor from a large company where I batch colour-corrected about a hundred images in minutes.
Sven, closing a macro-request as WONTFIX sounds very strange to me when it is one of a few major drawbacks with the Gimp (layer folders and proper batching being the others).
Wouldn't the non-destructive editing and repeating of actions you're referring to just apply within the same image?
No, the main point of the GEGL image processing graph is that you can easily apply the same processing steps to any image. It will essentially be macro recording, only better, and using a somewhat different approach.
I want to take a shot at this for GIMP 2.10 (which maybe will be 3.0, who knows) by rewriting the undo system to use the Command pattern.
Currently aiming for 3.6, putting on Future for now
Aiming for 3.6!? Are you serious?
With the current rate of development that would mean in 5 or 6 years. For a serious showstopper that many people badly needs.
Way to go! Keep it up. Much appreciated...
David, yes it means in 5 or 6 or 10 years, because we simply don't have
Your bitching really pisses me off. What *I* would really appreciate
was if you came around to IRC and offered your help.
Michael: I am not well versed into script-fu, the PDB, the relation between them, etc., so I have difficulty to see the amount of work involved in this task.
Do you think this is quite feasible with the existing GIMP architecture, and you only need a developer, or there are still some deep changes needed in GIMP/PDB/whatever?
I ask because I would be interested to develop this, after I finish the XDG stuff and some animation-related features I want to propose (so not right now, probably in a month or 2). Hence I'd like your opinion, and any pointer anyone would have on the best way to make this with GIMP architecture.
Jehan, this would also involve recording core stuff that is currently not available via the PDB. See comment 43 for the approach Martin suggested, changing the undo system to use the Command pattern (https://en.wikipedia.org/wiki/Command_pattern)
This would most likely provide a suitable foundation for a script recorder. Not sure if there has been any discussion and/or if there is any record of a discussion whether this is the best approach.
Thanks Michael. I'll have a closer look at what is the command pattern exactly later, when and if I ever really start to work on it.
Actually I have thought randomly about this feature in the last year, and I see 2 problems there:
1/ the internal code design (how do we implement function replay), only thing discussed in the ticket;
2/ the feature usage: what does the user expects to happen when one records.
I have several interrogations, for instance:
- You record a stroke. Do we only record coordinates and such, and when we replay, whatever is the current tool (can be different from record time) is used? Or do we also record a context at start of macro recording: which tool, brush, opacity, etc. (all what makes a context) is currently selected, and switch to it to a macro replay, then switch back at end of macro replay?
Actually both actions make sense. I could easily imagine someone wanting to replay actions with the exact same context, and someone else wanting to replay the exact same actions with different default. Maybe we could allow both kind of replay (one action replay-macro and replay-macro-with-context).
- All kind of actions on coordinates (stroke, selection, etc.), do we record absolute coordinates or percent, or something else? Like if you make a stroke at half of your canvas, and repeat the macro on a bigger or smaller canvas, do we stroke at the same coordinates (XXX px, not the middle in the second canvas), or at the relative position (middle)?
- What action exactly does a macro record or not? Like you switch to another shell, do you record this? If we don't, then, what about the macro: 1 recordable action, switch, 1 recordable action. When we replay this macro, both actions will happen on 1 single canvas, if we don't save the switch.
And many others. What do other drawing software with macros do about these?
Do we have a design paper about the feature? I could write a design proposal about this, after discussing with Aryeom, but I wonder if there are already any thoughts and opinion from the team.
It seems more than a shame that there has no been discussion of this proposed feature in almost two years.
In the 2001 discussion, it was proposed that recording actions to be played back might be tackled in version 2.0. Now GIMP is at version 2.8.14. If the reasons given for not implementing this feature—which would likely quadruple the usefulness of the GIMP—are valid (and I have no reason to suspect they are not valid), this means that the basic architecture of the GIMP has not been amended or redesigned in almost 14 years (to record every GUI action in some sort of format that would lend itself to be replayed as a script (not necessarily Script-Fu or Python-Fu).
I don't wish to sound critical, as I find GIMP to be hugely useful as it is. Whatever shortcomings GIMP may have, I am sure that it has been because of lack of programming resources rather than anyone's "fault". We should all be thankful for the boatloads of work that have been put into programming GIMP.
I thought, as did others before me, that the Undo stack could be a foundation for a record/playback feature, but apparently not enough state is saved to provide enough context to simply replay actions.
Perhaps by envisioning the playback function as a named entity that simply brings up the same dialogs in the same order in the GUI is an easier or intermediate target (with the proviso that the action of each dialog applies to the currently-selected window, not the window it was recorded in, of course). Even such a relatively feeble-minded automation would be useful for doing repetitive tasks, even if parameters within dialogs had to be changed if different from those recorded (if, indeed, they are recorded at all). This still leaves a myriad of questions about what to do with menu and tool choices and many other questions. But, if an action can be undone, the information to do so resides somewhere in the GIMP as currently written.
Forgive me my ignorance about GIMP programming as I have just joined this group and have not yet looked at the source...which would doubtless be a good idea before making assertions I know nothing about!
*** Bug 753740 has been marked as a duplicate of this bug. ***
Is anyone working on this? I have an active interest in this, and would like to have contact with current developers.
Noone's working on this. If you want to take a stab at this feature, the floor is yours :)
We mostly hang out on IRC. See http://www.gimp.org/irc.html. The majority of developers are in Europe and have day jobs, so you might want sticking around to have your questions answered.
*** Bug 763788 has been marked as a duplicate of this bug. ***
I'd like to vote for this feature also (Emacs has this for 30 years at least) ;-)
Is there voting going on here? Hmmm, most likely not. Perhaps a search for a developer? Why, yes indeed!
As to the macro recorder, I have recently written a grant to the US ORI (Office of Research Integrity) to develop this feature. If I get the grant, I will actually have money to hire a developer to work with me on this. If I don't get the grant, I will try it myself. I will post a note indicating my success. I hope to have this underway in about 3-4 months, by August, 2016.
Nice! Please keep us in the loop, Paul.
Making this bug a dependency for bug 763788. Once the script/macro recorder is in, extending it out so that moving the last X actions recorded to a new layer will be an easy lift.