Ondrej Paska Blog

Generating images from code with Photopea

Advertisements

Photopea is a free Photoshop alternative that lives in the browser. If you haven’t used it already, you should definitely give it a try! It’s fast, requires no installation and will feel very comfortable to anyone who is used to Photoshop’s interface.

The part I want to focus on is the scripting it supports – mainly how to make it generate a zip file with PNG images based on a template.

As in Photoshop, scripts are written in Javascript using an API for interacting with the elements in the document. The API can be a bit puzzling, so here are some common functions:

app.activeDocument.layerSets // get all folders in a document
app.activeDocument.artLayers // get all layers in a document (not in folders)
layer.visible = true/false // toggle layer visibility
layer.textItem.contents = "" // set text to a text layer
layer.translate(layer.bounds[0]-X, layer.bounds[1]-Y) // move layer to X, Y

I started experimenting with this because for our upcoming board-game we have data for 32 cards in Google Sheets – name, strength, abilities etc. Generating prototypes for printing by hand was cumbersome and error-prone. So I decided to automate it. Similarly you might generate business cards, invitations, etc.

The solution I came up with takes data from Google Sheets in JSON form (scripting in Google Sheets is for another blog post). Based on the data, it shows/hides some layers and changes the text in text layers.

Here are some utility functions:

function getLayer(s){ // finds layer by name
 var layers = app.activeDocument.layers;
 for(var i = 0; i < layers.length; i++ ){
  if( layers[i].name == s ) return layers[i];
 }
 return null;
}

function getLayerSet(s){  // finds folder by name
 var layers = app.activeDocument.layerSets;
 for(var i = 0; i < layers.length; i++ ){
  if( layers[i].name == s ) return layers[i];
 }
 return null;
}

function activateOnly(s, set){ // activates one layer in a folder
 set = set || app.activeDocument;
 var layers = set.artLayers;
 for(var i = 0; i < layers.length; i++ ){
  layers[i].visible = layers[i].name == s;
 }
}

 

For each data item, show the correct layers and text…

activateOnly( item.color +" border", getLayerSet("border") );
  
var namelayer = getLayer("Name Text");   
namelayer.textItem.contents = item.name;

 

Example layer structure

… and export it as PNG.

    var opts = new ExportOptionsSaveForWeb();
    opts.format = SaveDocumentType.PNG;
    opts.PNG8 = false;
    opts.quality = 100;
    
    pngFile = new File(item.folder+"/"+item.name+".png");
    app.activeDocument.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);

 

Saving this script in a jsx file, you can drag it to Photopea to run it.

After the script ends, it spits out a .zip file with all the exported images in a folder structure. On my machine it generates 32 high-res PNGs in about 12 seconds – much faster than Photoshop!

There are some limits on what you can do, for example I haven’t figured out how to change the color of only part of a text.

Hope you find this useful.

Advertisements

Advertisements