How to load an image into an action's image well

Let's say I have this action:

image

 
I have an image file on disk that I want to put into the image well, like this:

image

 
Yes, I could change the action to point to the image file on disk, but in this case I specifically don't want to do that.

I assume it can be done with JXA/Obj-C. I already know how to extract an image to disk (please forgive any typos here - I trimmed some existing code for clarity):

function extractImageToDisk(actionDict, imagePropertyKey, outputFilePath) {
	const imageData = actionDict[imagePropertyKey];
	if (!imageData)
		throw new Error(`Could not find image data for imagePropertyKey "${imagePropertyKey}"`);
	var image = $.NSImage.alloc.initWithData(imageData);
	var tiff = image.TIFFRepresentation;
	tiff.writeToFileAtomically(outputFilePath, true);
}

So I basically need the reverse of this.

If I can't figure out how to do it with Obj-C, I'll probably convert the image to base64, and stick it in the action's XML:

<dict>
	...
	<key>Image</key>
	<data>
	TU0AKgAABZyAP+BP8AQWDQeEQmFQuGQ2HQ+IRGJROKRWLRWBwSLxuOR2PR+Q
	SGLRmRSWTSeUSmPySVS2TP2YAB5TMAPubAAHTkAAieS6fROWT+XPqiABpUcA
	...
	AAMAAAACZmYAAwAAAAJmZgADAAAAAmZmAAAAAjMzNAAAAAACMzM0AAAAAAIz
	MzQA
	</data>
	...
</dict>

Thanks.

Won't you be using JXA to do that anyway? Quickly thrown together AS version:

set thePicInBase64 to "TU0AK..." -- your b64 string here

tell application "Keyboard Maestro"
	tell item 1 of (get selection)
		set theXML to xml
		if theXML contains "<data>" then
			set AppleScript's text item delimiters to "<data>"
			set firstPart to text item 1 of theXML
			set AppleScript's text item delimiters to "</data>"
			set secondPart to text item 2 of theXML
			set xml to (firstPart & "<data>" & thePicInBase64 & "</data>" & secondPart)
		else
			set AppleScript's text item delimiters to "<key>MacroActionType</key>"
			set firstPart to text item 1 of theXML
			set secondPart to text item 2 of theXML
			set xml to (firstPart & "<key>Image</key><data>" & thePicInBase64 & "</data><key>MacroActionType</key>" & secondPart)
		end if
	end tell
end tell

Or are you trying to do this without having the Editor open?

Obviously the above will be more difficult with eg multiple image conditions, but JXA should be able to do a better job of manipulating the XML than AS's TIDs. selection only used for testing, you could pass in an action UUID any way you like instead.

Thanks, and perhaps I wasn't clear. Yes, I can do that in JXA easily, and I will if I need to. But what I was hoping for is a JXA/Obj-C method, similar to the JXA code I posted.

But certainly - thanks for the code! (LOL - I mistyped that last word as "coed" - I think that would belong in a different website...)

Ah, gotcha. I thought the code was to extract the relevant bits of any old image to disk, ready to use in the image well -- didn't realise it was specifically to extract a KM action's image.

Isn't that what it boils down to anyway – deriving XML with the desired <data> value for the <image> key ?

What is the type and source of the actionDict argument in your extractImageToDisk ?

Well, yes, it is. So I guess you're saying that I should just do it the string manipulation way and stop worrying about it?

1 Like

I should just do it the string manipulation way

If the output data really is of type String, then String formation seems right.

But what is the type of your actionDict argument there ?

(Am I perhaps missing something ?)

No, you're not missing anything. The "type" is any action that can have an image well. To wit:

  • MouseMoveAndClick
  • FindImage
  • SetClipboardToImage
  • PauseUntil (found image)
  • IfThenElse (found image condition)
  • For (found image collection)

The only reason I was thinking about doing it with Obj-C was because that's how I extracted the image to disk in the first place - this is sort-of an "undo" of that.

But the "how" of it is totally irrelevant, in the long run.

But for the type – more specifically – is it an NSXML parse object ?

(I'm not sure what data-types your list of names there are bound to)

Yes it's in an NSXML object, but I also have the XML itself. So no big deal either way.

The final result is handled by using KM's "Paste Action and Replace", so the XML itself is the desired result.