Plug-in for stitching arbitrary number of images together

Hello! I’m looking for some help on a plug-in for stitching images of equal dimensions end-to-end into a single image. The documentation for plug-ins has me a little confused, specifically the word that seems to be missing from sentence “processAsset is called for every image passed to this node. Return true to continue processing the, or false to not.”

My plug-in, which currently does not work as I intend it to, is this:

module.exports = {
    accumulator: null,
    accumulatorWidth: 0,
    workflowEnd: function (document, rbnode) {
        this.accumulator = null;
        this.accumulatorWidth = 0;
    },
    processAsset: function (document, rbnode, asset) {
        if (!this.accumulator) {
            this.accumulator = asset.emptyImageAccumulator();
            this.accumulator.drawCIImage(asset.CIImage());
            this.accumulatorWidth += asset.imageWidth();
            return true;
        }

        this.accumulatorWidth += asset.imageWidth();
        const newAccumulator = asset.emptyImageAccumulatorOfSize(
            CGSizeMake(this.accumulatorWidth, asset.imageHeight())
        );
        newAccumulator.drawCIImage(this.accumulator.image());
        newAccumulator.drawCIImage(
            asset
                .CIImage()
                .imageByApplyingTransform(
                    CGAffineTransformMakeTranslation(
                        this.accumulatorWidth - asset.imageWidth(),
                        0
                    )
                )
        );
        this.accumulator = newAccumulator;
        asset.setCIImage(newAccumulator.image());
        return true;
    },
};

If I don’t reset the accumulator after the workflow ends I get a result closer to what I want (the images stitched together end-to-end), but that’s only after running the workflow twice. I think this is a symptom of me misunderstanding when processAsset should return true or false.

Additionally, is there a faster way to reload plug-ins than this?

  1. delete the plug-in node
  2. quit Retrobatch
  3. delete the .retrobatchplugin from ~Library/Application Support/Retrobatch/Plug-Ins
  4. double-click the plugin and install it
  5. re-open Retrobatch
  6. add the plug-in node back

I have an answer for you, but it’s not quite ready yet (I’m making some additions to RB to make what you want to do possible). Hopefully it’ll be ready sometime tomorrow.

As for reloading plugins, with the current version of RB, quitting and restarting is the way to do this. You don’t need to move the plugin in and out.

OK, good news, I’ve got a solution for you.

The first one, and I don’t know why I didn’t this of this originally, is to use the Image Grid node with the “Count Across” setting to something really big like 1000 (and Down set to 1).

But it’s now possible using a plugin with the latest build of Retrobatch which I’ve just put up here: Latest Builds from Flying Meat

Here’s what your plugin will look like:

module.exports = {
    
    assets: [],
    inputKeys: [],
    attributes: {},
    
    processAsset: function(document, rbnode, asset) {
        this.assets.push(asset);
        // Returning false means that Retrobatch will no longer continue with this asset.
        return false;
    },
    
    processInputs: function(document, rbnode) {
        
        var totalWidth = 0;
        var wideImage = null;
        
        this.assets.forEach(asset => {
            var image = asset.CIImage();
            
            if (wideImage == null) {
                wideImage = image;
                totalWidth = asset.imageSize().width;
            }
            else {
                image = image.imageByApplyingTransform(CGAffineTransformMakeTranslation(totalWidth, 0));
                wideImage = wideImage.imageByCompositingOverImage(image);
                totalWidth += asset.imageSize().width;
            }
            
        });
        
        var firstAsset = this.assets[0].copy();
        firstAsset.setCIImage(wideImage);
        
        rbnode.processAsset(firstAsset);
    },
    
};

It introduces a new function named processInputs which RB will call when it wants your plugin to push out any images it has made or loaded in any way. In this method the plugin stitches together all the images that have been collected in processAsset and then sends it through the rest of the nodes that fall after it.

I’ve also added a new command to the Console: /reload, which will ask Retrobatch to restart and reload the plugins (by shutting down the JS interpreter and then starting it back up again when the workflow is run).

You can also type /help in the Console to see other commands, or control click on the > symbol next to the Console input.

Let me know if you have any feedback or ideas! This isn’t in the documentation yet because I want to be able to tweak it based on feedback.

-gus