Batch Image Generation With JavaScript

Publish date

In this article we'll quickly outline how we can use Pintura to generate multiple images with JavaScript, or generate multiple variations of the same image.

Pintura exports the processDefaultImage function, which is intended for headless image processing, meaning image processing without an interface.

Pintura accepts various image sources, but in this article we'll stick to using a URL.

Headless Image Processing

Let's first process a single image, in the example below we automatically crop the source image into a square using the imageCropAspectRatio property.

import { processDefaultImage } from './pintura.js';

// This crops the image into a square
const result = await processDefaultImage('image.jpeg', {
    imageCropAspectRatio: 1,
});

// Logs the resulting image information { src:…, dest:… , imageState:… }
console.log(result);

// Show the processed image
const image = new Image();
image.style.maxWidth = '100%';
image.src = URL.createObjectURL(result.dest);
document.body.append(image);

The output contained in the result variable includes the src image as a file, the resulting dest image as a file, and the computed imageState which was used to create the image (in this case it contains our value of 1 for the cropAspectRatio).

We can also pass other or multiple image manipulation properties to the processDefaultImage function, or an imageState

import { processDefaultImage, colorStringToColorArray } from './pintura.js';

// This crops the image into a square
const result = await processDefaultImage('image.jpeg', {
    imageCropAspectRatio: 1,
    imageDecoration: [
        {
            x: 0,
            y: 0,
            width: '100%',
            height: 300,
            backgroundColor: colorStringToColorArray('rgba(0, 0, 0, .8)'),
        },
        {
            x: 100,
            y: 100,
            text: 'Hello World',
            fontWeight: 'bold',
            fontSize: 100,
            color: colorStringToColorArray('rgb(255, 255, 255)'),
        },
    ],
});

// Logs the resulting image information { src:…, dest:… , imageState:… }
console.log(result);

// Show the processed image
const image = new Image();
image.style.maxWidth = '100%';
image.src = URL.createObjectURL(result.dest);
document.body.append(image);

Batch Processing Multiple Images

The processDefaultImage function is asynchronous and this allows us to loop over multiple images and then process them all in the same way.

import { processDefaultImage } from './pintura.js';

// The input URLs
const images = ['boats.jpeg', 'elephant.jpeg', 'mountains.jpeg'];

const results = [];

for (const image of images) {
    // Crop to a square
    const result = await processDefaultImage(image, {
        imageCropAspectRatio: 1,
    });

    // Add to results
    results.push(result);
}

// Logs the resulting images
console.log(results);

// Append resulting images to page
for (const result of results) {
    const image = new Image();
    image.style.maxWidth = '100%';
    image.src = URL.createObjectURL(result.dest);
    document.body.append(image);
}

Batch Processing With Multiple Transformations

We can also do this the other way around, we can define various crop aspect ratios and process the same image in different ways.

import { processDefaultImage } from './pintura.js';

// The aspect ratios we want to crop to (square, portrait, landscape)
const aspectRatios = [1, 3 / 4, 16 / 9];

const results = [];

for (const aspectRatio of aspectRatios) {
    // Crop to a square
    const result = await processDefaultImage('image.jpeg', {
        imageCropAspectRatio: aspectRatio,
    });

    // Add to results
    results.push(result);
}

// Logs the resulting images
console.log(results);

// Append resulting images to page
for (const result of results) {
    const image = new Image();
    image.style.maxWidth = '100%';
    image.src = URL.createObjectURL(result.dest);
    document.body.append(image);
}

And we can apply multiple transformations.

import { processDefaultImage } from './pintura.js';

// The image transformations
const aspectRatios = [1, 3 / 4, 16 / 9];
const maxSizes = [64, 256, 512];

const results = [];

for (const aspectRatio of aspectRatios) {
    for (const maxSize of maxSizes) {
        // Crop and resize
        const result = await processDefaultImage('image.jpeg', {
            imageCropAspectRatio: aspectRatio,
            imageWriter: {
                targetSize: {
                    width: maxSize,
                    height: maxSize,
                },
            },
        });

        // Add to results
        results.push(result);
    }
}

// Logs the resulting images
console.log(results);

// Append resulting images to page
for (const result of results) {
    const image = new Image();
    image.style.maxWidth = '100%';
    image.src = URL.createObjectURL(result.dest);
    document.body.append(image);
}

Browser vs Node

Pintura is a browser based library, it relies on APIs available in the browser. Running the above scripts in a NodeJS environment will not work as Node doesn't expose the necessary API's.

If we do want to run Pintura on our server we can use a headless browser.

That's it

We learned how to use the Pintura processDefaultImage function to programmatically process multiple images or apply multiple transformations to a single image with JavaScript.

I hope you found this an interesting, feel free to ask any questions here.