I need to execute the following set of actions dozens of times with different images (the two red actions will always use the same image, however).
Is there a better way to do this than copying these six actions dozens of times and pasting each image in two places?
It would be ideal if I could somehow pass the image to a subroutine in the event I need to change the pauses/scroll length, but I'm aware that subroutines only accept variables as parameters, not images.
I'm not sure this will help, but maybe: You can reference a file that contains an image, instead of the image itself. And that file reference can be a variable, so this works:
Untried, but you could set the actions to use a file path to an image. You could then either a) hard-code the file path and rewrite that file to be a different image as required, or b) reference different files by variable.
I'd try the second, so your sub would be something like
Another method -- set the action to use an image from a Named Clipboard, and set the contents of that Clipboard any time you want a change of image. No sub required.
Two people suggested that you pass the image as a filename. I'm sure that will work, but I avoid that because I'm always concerned about performance. So what I do is "pass" the image to a subroutine by first assigning the image to a "global named image clipboard" and then calling the subroutine.
So in a way I am able to "pass an image to a subroutine" by doing that. I just have to remember the name of the named clipboard for each. Something like this:
Notice how I assign an image to a named clipboard (called "FunctionImage") and then I call my subroutine (called "Process".) Notice that I have several additional parameters to my subroutine. One of them is called Fuzziness, which is something special that I do to address the fact that the image search action in KM doesn't allow a variable to specify the amount of fuzziness. I also have a parameter called Conditions which does even more magic that I won't talk about here.
Perhaps. My macro functionally works fine, but I'm noticing an odd performance issue that I want to work out first. It seems like the KM Engine is experiencing random pauses (about 0.3 seconds per call) when I use this macro. This is very annoying and unexpected.
Perhaps if I trim down some of the features of my macro I can eliminate the Engine pauses.
An interesting point -- but have you tested in any way? I haven't, but my theory is that reading from a file may actually lead to a faster-executing macro. The reason being that SSD file access is in the region of 50-100 microseconds and, for file sizes we're talking about, read time is negligible. But the "Set Named Clipboard" action takes at least a millisecond.
Of course, execution speed isn't the only issue when considering performance -- and it will depend on how many times you call your sub between each Clipboard reset.
I can't speak for @Airy's method -- but something similar would be easy enough to do with an "Execute an AppleScript" that created the appropriate XML then ran it with tell application "Keyboard Maestro Engine" to do script theXML
You could start by setting up an action the way you want, copying it as XML, pasting into Script Editor, and seeing which bits you'd want to make variables.
Also, macOS loves to cache things, so I imagine that after that first read, it won't touch the file on the disk again unless it's modified. After the first use, I would guess that the speed gets even quicker.
No. I have not tested it. Perhaps I was too judgmental regarding performance. I did consider testing it but for quite a while I've been battling some kind of virus so I've been lazier than usual. I think it's nearing the end of its course in me, however.
I tend to oscillate on this -- at the moment I'm in a "don't worry about performance until performance is a worry" phase. Next week I'll be trying to shave microseconds of my macros for particular reason
What I more generally worry about with subroutines is the unnecessary use of global variables -- and a Named Clipboard is essentially a global variable. The Clipboard will probably still contain the correct data by the time the sub access it, but there's a chance it won't.
I'm still feeling bad from a false conclusion I jumped to in the 80s when floppy disks were how we all stored data. Someone invented a floppy disk driver that compresses all the data before writing it to the floppy. My reaction was "too bad that will slow down the PC, because of the extra steps involved." Later I realized that since disk I/O was much slower than RAM I/O, the compression actually sped up the whole process rather than slowing it down.
So maybe I'm making the same mistake again, which will make me feel bad for another 40 years.
Here is just a thought … what’s about having one version of a particular image in it’s original form and store it as a ****.txt file where the contents are the image in Base64?
Since the subroutine is desired to compare everything related to the image except its Name I would use this way to
Have one exact copy of the image
Have a copy of it in text (which is maybe way less heavy it terms of used space)
Use the openCV Library to compare the temporary from Base64 restored image to its original instead of keeping the same file twice in several different locations and trying to compare only by checksum and hashes - what I think is never exactly the same since at least one (either the checksum or the md5 hash or even both) isn’t (or aren’t) comparable between both files.
I think openCV is the best way to get exactly the desired 100% in comparison here.
The only possibility that this is not the case is if you manipulated the image beforehand - and I believe that even then you’d be able to tell the difference between the two images in some way ….
If it is desired to do something with things like Fuzzyness and Screen Coordinates and even the handling of location data I think with a big amount of images the best and possibly the most efficient way would be to store the data in a SQLite Database.
But that depends entirely on the Workflow but the more images you have to deal with, the better is this as the way of solution to choose. Besides the fact that you could directly create an encrypted SQLite Database with Python so only you could access your data and no one else.
Also the amount of data stored by KM is highly reduced what makes Plist as small as possible and the whole thing shareable between many machines.
Maybe a little overkill at first sight - but on the second look a slick solution… at least to me.