Macro to combine arbitrarily sized images?

Hey folks,

I'm looking for some help. I often need to combine two (or sometimes more) screenshots for TidBITS articles. Most of the time, it's two iPhone or Apple Watch screenshots, but I've started trying to use Federico Viticci's Apple Frames shortcut for that. (I need to tweak that to work with the 10.5-inch iPad Pro and 38mm Apple Watch too, but that's another issue.)

But every now and then I end up with several Mac screenshots that I need to put side-by-side with 20 pixels of white space between them. I can map out roughly how this would work in Keyboard Maestro, but every time I start, it becomes clear that it will take so many hours for me to figure out the syntax that I shelve it in favor of writing an article, given that it's not difficult to combine screenshots in the now-defunct Napkin app.

Has anyone built a macro like this that I could start from? Basically, it would need to read the height and width of all the images, create a canvas large enough to hold them with the 20 pixels of white space between, and plop them onto the canvas in the right places in order of selection, and then save the combined PNG file to the same location.

Thanks!

1 Like

One way to do this would be to create a 20x1-pixel white image as a spacer (spacer.png in the following command) and let ImageMagick do the work in an Execute Shell Script action:

convert ss-1.png spacer.png ss-2.png +append ss-combined.png

You could parse the image filenames from a finder selection and pass them on the Execute Shell Script action as KM variables.

So no need to measure the images or create a large enough canvas to line up two images in one with a 20-pixel space between them.

Hope that helps.

1 Like

I found different way to achieve this using KM canvas actions.

I made the assumptions that there were three images he wanted to insert. For the purposes of this macro I created three images with different sizes from random locations on the current screen. And I created three clipboards to solve this. It's entirely possible that I didn't do exactly what he wanted. If so, he should tell me what I'm doing wrong and I can correct it.

Test ClipBoard Merger.kmmacros (11 KB)

It's very likely that I'm doing something slightly differently from what is being asked. If so, he can clarify his concern and I can correct it.

Oh, that's an interesting thought. I hadn't considered Image Magick, not being a command-line person for the most part. I'll have to see if I can get it installed and test this idea.

Thanks! Yes, you're doing something just a bit different. What I'm looking for is a way to take several arbitrarily sized screenshots that already exist in the Finder (probably on the Desktop) and then combine them into a single image, with everything top-aligned and separated by 20 pixels.

So where you're creating images within the macro, I'd just be selecting files in the Finder and then running the macro.

Let me know if you have trouble getting it going. I have a merge photos script on my Mac but I’m on my iPhone at the moment.

Yes, I try to use native KM actions in my solutions. I eschew AppleScript, Javascript Swift, HTML, CSS and anything else because I think that's a lot to learn.

My code example above was hardcoded for exactly three images only. I'm pretty sure we could enhance that to N images if we wanted to, but that would heave made the example complicated.

FWIW… using convert which is part of imagemagick, you can 'merge' two files "side by side" like this:

convert -bordercolor "$COLOR_NAME" -border 2.5x5 "$FOO" "$BAR" +append "$OUT"

In this case, $FOO will be on the left and $BAR will be on the right.

Here's an example using real values:

convert -bordercolor blue -border 2.5x5 "IMG_0116.JPG" "IMG_0117.JPG" +append "Merged1.jpg"

The "2.5x5" determines the width of the border around each image.

Instead of "2.5x5" imagine it was "AxB".

Generally speaking, you want "A" to be half of "B" because when the two images are next to each other, "$FOO" will have "A" on its right edge, and "$BAR" will have "A" on its left edge, meaning that the total width of the border in the middle of "$FOO" and "$BAR" is "A+A".

So you want A+A = B.

(I think I'm remembering that correctly.)

Play around with different values to see this in action.

If "$FOO" is portrait and "$BAR" is landscape" (or vice versa), they will have their tops aligned, which is I think what you wanted.

I hope this helps. Let me know if you have questions, and I'll see if I know the answer.


p.s. if you wanted $FOO to be on top of $BAR instead of next to it, you would use:

convert -bordercolor ${BORDER_COLOR} -border 5x2.5 "$FOO" "$BAR" -append "$OUT"

Note two differences:

  1. instead of +append we are using -append
  2. instead of 2.5x5 for the border we are using 5x2.5

So I neglected this part of my answer. The closest I can get with my method would be this:

convert -bordercolor "white" -border 10x20 "IMG_0116.JPG" "IMG_0117.JPG" +append Output.jpg

That will give:

  • 20px of white at the top
  • 20px of white at the bottom
  • 20px of white between both images
  • 10px of white on the left margin
  • 10px of white on the right margin

But if what you want is 0px on all sides except at the "seam" where the two images meet… I'm not sure how to do that.

There are other options like gravity and splice which I think can do that… but I haven't yet found an example that I can understand enough to explain how to do it.

convert (and imagemagick in general) is basically a black art to me, and even when I read examples on the web, I don't always understand what they are saying.

In ImageMagick, you also have Montage:

The " montage " command is designed to produce an array of thumbnail images. Sort of like a proof sheet of a large collection of images.

https://www.imagemagick.org/Usage/montage/

Lovely stuff, everyone, thanks so much! Once I finish prepping for a MUG presentation tonight, I'll see if I can get one or more of these solutions working and report back.

I've been suggesting for years that, like it recently did with OCR, KM should incorporate ImageMagick directly into a KM action. The IM license would indeed allow KM to do that (https://imagemagick.org/script/license.php).

I can imagine how this could be done to address all ~75 IM actions in a single KM action. Think of how the KM action Search Using Regular Expression works. It would work like that. There would be an expanding number of fields available. The first expanding field would be for the filename parameters. Here's a complete list of the six expanding field lists as taken from the IM site:

  1. one or more required input filenames.
  2. zero, one, or more image settings.
  3. zero, one, or more image operators.
  4. zero, one, or more image sequence operators.
  5. zero, one, or more image stacks.
  6. zero or one output image filenames.

So a single KM action, with six expanding fields for the above six types of parameters, could probably handle all possibilities. But even if I'm wrong about this, a single parameter would certainly suffice if that parameter simply passed all the parameters to the IM binary.