v8.32.2

Editor Exported Methods And Properties

The functions, properties, and defaults related to image editing that are exported by the Pintura module.

Export Description
createDefaultImageOrienter() Creates a helper object to correctly orient images.
createDefaultImageReader(options) Creates the default image reader. This is the array of processes the editor uses to read image data.
createDefaultImageWriter(options) Creates the default image writer. This is the array of processes the editor uses to write image data.
createDefaultImageScrambler(options) Creates the default image scrambler. This is a function that receives an ImageBitmap or ImageData object and returns a canvas with scrambled data.
createDefaultShapePreprocessor() Creates the default shape preprocessor used for parsing lineEnd styles and frame styles.
createShapePreprocessor(processors[]) Accepts a shape processor configuration and returns a function that can be assigned to the editor shapePreprocessor property.
createDefaultFrameStyles() Generates the default frame style object.
createDefaultLineEndStyles() Generates the default line style object.
createFrameStyleProcessor(styles) Merge custom frame styles with the default frame styles.
createLineEndProcessor(styles) Merge custom line end styles with the default line end styles.
processImage(file, options) processes the file with supplied properties.
processDefaultImage(file, options) Same as processImage but sets default image reader, image writer and image orienter.
legacyDataToImageState(editorRef, imageSize, legacyDataObj) Converts a Pintura Image Editor legacy data object to an imageState object.

createDefaultImageOrienter

The createDefaultImageOrienter function returns a default image orientation helper object containing a read and an apply method to read EXIF orientation information and to write EXIF orientation information.

const imageOrienter = createDefaultImageOrienter();

console.log(imageOrienter);
// logs: { read: function, apply: function }

The returned object should be assigned to the imageOrienter property on your editor instance.

createDefaultImageReader

The createDefaultImageReader function returns the default image reader steps. This is an array of processes the editor runs to read image data.

It can read resources of type File, Blob, Data URL, URL, HTMLCanvasElement, and HTMLImageElement. It will also automatically correct mobile photo orientation when needed.

The default image reader can read images that are supported by the clients browser. In general these image formats are supported by all major browsers.

  • image/gif
  • image/png
  • image/jpeg
  • image/webp
  • image/bmp
  • image/svg

If needed we can use the preprocessImageFile hook to read additional image formats (for example HEIC).

The returned image reader object should be assigned to the editor imageReader property.

Export Default value Description
orientImage
true
Auto corrects the orientation of mobile photos.
outputProps
['src', 'dest', 'size']
Which properties to retain on the output data object.
preprocessImageFile
async (file) => (file)
Allows preprocessing the image file, for example to turn a HEIC image into a browser supported image format.
<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createDefaultImageReader,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageReader: createDefaultImageReader({
            // Fix image orientation
            orientImage: true,

            // Disable output prop filter
            outputProps: [],
        }),
    });
</script>

The createDefaultImageReader result object is passed along with the 'load' event, see an example of this object below.

{
    // the resulting file
    dest: {
        name: 'my-image.jpeg',
        lastModified: 1605802185485,
        size: 128000,
        type: 'image/jpeg',
    },
    // the image size
    size: {
        width: 1280,
        height: 1024,
    },
    // the original source
    src: './images/my-image.jpeg',
}

preprocessImageFile

The example below shows how to load HEIC/HEIF images using Heic2any in the preprocessImageFile hook.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<script src="./heic2any.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        processImage,
        createDefaultImageReader,
        blobToFile,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageReader: createDefaultImageReader({
            preprocessImageFile: async (file, options, onprogress) => {
                // If is not of type HEIC we skip the file
                if (!/heic/.test(file.type)) return file;

                // Let's turn the HEIC image into JPEG so the browser can read it
                const blob = await heic2any({
                    blob: file,
                    toType: 'image/jpeg',
                    quality: 0.94,
                });

                // The editor expects a File so let's convert our Blob
                return blobToFile(blob, file.name);
            },
        }),
    });
</script>

createDefaultImageWriter

The createDefaultImageWriter function returns a default image writer array. This is an array of processes the editor runs to write the output image data.

By default it will output the src image file, the dest image file, and the imageState. If a store has been defined it will also return the store object.

Export Default value Description
canvasMemoryLimit
isIOS() ? 4096 * 4096 : Infinity
Memory limit to keep in account while drawing to canvas.
orientImage
true
Auto corrects the orientation of mobile photos.
copyImageHead
true
Copy the image head of the origin image to the output image. Only used when format is set to 'file'.
mimeType
undefined
Image mime type as a string, by default uses input image mime type.
quality
undefined
A Number between 0 and 1 indicating image quality if the requested type is image/jpeg or image/webp. If this argument is anything else, the default values 0.92 and 0.80 are used for image/jpeg and image/webp respectively. Other arguments are ignored.
renameFile
undefined
A synchronous function that receives the input file and expects a filename in return. Only called for 'file' format.
targetSize
undefined
The output size of the image
imageDataResizer
undefined
The function to use for resizing the imageData.
format
'file'
Format of dest property, can be set to 'file', 'imageData', or 'canvas'.
store
undefined
URL to POST FormData to, object to finetune FormData, or async function for custom file upload or storage solution. URL and object modes are only used when format is set to 'file', for other output formats use async function.
outputProps
['src', 'dest', 'imageState', 'store']
Which properties to retain on the output data object.
preprocessImageSource
async (imageSource) => (imageSource)
Allows preprocessing the source image data, for example to apply third party image optimisations or converting the file format before applying the imageState.
preprocessImageState
async (imageState) => (imageState)
Allows preprocessing the imageState, for example to replace shape placeholder text with actual content.
postprocessImageData
async (imageData) => (imageData)
Allows postprocessing the image data, for example to apply a circular crop mask.
postprocessImageBlob
async ({ src, blob, imageData }) => (blob)
Allows postprocessing the image blob, for example to convert an image to a format that isn't natively supported by the browser.

An example implementation of createDefaultImageWriter.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createDefaultImageWriter,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: createDefaultImageWriter({
            // Scale all input canvas data to fit a 4096 * 4096 rectangle
            canvasMemoryLimit: 4096 * 4096,

            // Fix image orientation
            orientImage: true,

            // Don't retain image EXIF data
            copyImageHead: false,

            // Convert all input images to jpegs
            mimeType: 'image/jpeg',

            // Reduce quality to 50%
            quality: 0.5,

            // Post images to API at './upload'
            store: './upload',

            // Limit size of output to this size
            targetSize: {
                width: 640,
                height: 480,
                fit: 'contain',
                upscale: false,
            },

            // Show all output props
            outputProps: [],
        }),
    });
</script>

canvasMemoryLimit

The amount of memory in pixels the browser can allocate to a canvas element. By default this is limited to 4096 * 4096 on iOS.

mimeType

The output image format. By default Pintura Image Editor can output in the image formats supported by the Canvas toBlob method. In general these image formats are supported by all major browsers.

  • image/png
  • image/jpeg
  • image/webp

The following snippet converts all files to JPEGs and applies a slight compression to the result.

createDefaultImageWriter({
    mimeType: 'image/jpeg',
    quality: 80,
});

renameFile

Allows dynamic renaming of the output file.

createDefaultImageWriter({
    renameFile: (file) =>
        `output_${name.substr(0, name.lastIndexOf('.'))}.jpeg`,
});

targetSize

Limit the output size of images to the defined width and height.

Export Default value Description
width
undefined
The target width of the output image.
height
undefined
The target height of the output image.
fit
'contain'
The method of resizing the input image, can be set to 'contain', 'cover', or 'force'.
upscale
false
Should the input image data be upscaled to the supplied width and height.

Make sure output images are contained within a 640 × 640 rectangle. If images are smaller they won't be upscaled.

createDefaultImageWriter({
    targetSize: {
        width: 640,
        height: 640,
        fit: 'contain',
        upscale: false,
    },
});

imageDataResizer

By default Pintura resizes images with a compact and relatively fast bilinear algorithm. While this results in perfectly fine output for most graphics, it can be sub-optimal when we're resizing high contrast imagery (like logo's) to very small sizes.

To work around this the imageDataResizer property enables us to supply our own resizing logic.

In the example below we configure pica to resize imageData.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<script src="./pica.js"></script>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createDefaultImageWriter,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: createDefaultImageWriter({
            targetSize: {
                width: 640,
                height: 640,
                fit: 'contain',
                upscale: false,
            },
            // use our custom pica resizer
            imageDataResizer: (imageData, outputWidth, outputHeight) =>
                new Promise((resolve) => {
                    pica()
                        .resizeBuffer({
                            // source data
                            src: imageData.data,

                            // source source width and height
                            width: imageData.width,
                            height: imageData.height,

                            // output width and height
                            toWidth: outputWidth,
                            toHeight: outputHeight,
                        })
                        .then((buffer) => {
                            // turn ArrayBuffer into new image data object and return to Pintura
                            const imageData = new ImageData(
                                outputWidth,
                                outputHeight
                            );
                            imageData.data.set(buffer);
                            resolve(imageData);
                        });
                }),
        }),
    });
</script>

store

The store property accepts a URL, a store configuration object, or a Function.

If we set a URL the editor will POST the output file and image state to that location as FormData. It will use "dest" as name for the file field, and "imageState" as name for the JSON string of the imageState object.

The XMLHttpRequest instance used to POST the data will be stored in the store property of the image writer output data object.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: {
            store: './my-custom-upload',
        },
    });

    editor.on('process', (imageWriterResult) => {
        const { store, dest } = imageWriterResult;
        // 'store' is the XMLHttpRequest instance used
        // for uploading the file, it contains
        // all XHR request information
    });
</script>

We can pass a configuration object to alter the defaults fields or add additional fields. It still allows us to set the url but now we can set a dataset Function. This Function receives the state and allows selecting data and naming fields.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: {
            store: './my-custom-upload',
            dataset: (state) => [
                ['imageFile', state.dest, state.dest.name],
                ['imageState', state.imageState],
            ],
        },
    });
</script>

If we need more control we can set a Function to the store property. This Function should return a Promise.

In the example below we run a custom upload function to store data in the imageState.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: {
            store: (state, options, onprogress) =>
                new Promise((resolve, reject) => {
                    const { dest } = state;

                    // create a formdata object to send to the server
                    const formData = new FormData();
                    formData.append('image', dest, dest.name);

                    // create a request object
                    const request = new XMLHttpRequest();
                    request.open('POST', './upload');

                    // show progress in interface
                    request.upload.onprogress = onprogress;

                    // catch errors
                    request.onerror = () =>
                        reject('oh no something went wrong!');
                    request.ontimeout = () =>
                        reject('oh no request timed out!');

                    // handle success state
                    request.onload = () => {
                        if (request.status >= 200 && request.status < 300) {
                            // store request in state so it can be accessed by other processes
                            state.store = request;
                            resolve(state);
                        } else {
                            reject('oh no something went wrong!');
                        }
                    };

                    // start uploading the image
                    request.send(formData);
                }),
        },
    });
</script>

preprocessImageState

This hook allows us to pre-process the imageState object before it's used to generate the output image.

In the example below we replace all name placeholders in annotation text values with the name "John Connor".

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor, processImage } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: {
            preprocessImageState: (imageState) => {
                // create new annotation array
                imageState.annotation = imageState.annotation.map((shape) => {
                    // this is not a text shape so skip
                    if (!shape.text) return shape;

                    // replace placeholders in text properties
                    shape.text = shape.text.replace(/{name}/g, 'John Connor');

                    return shape;
                });

                // return updated image state
                return imageState;
            },
        },
    });
</script>

postprocessImageData

Run post image processing on the imageData the editor outputs. The example snippet below will apply a circular crop mask to the image.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor, processImage } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageWriter: {
            postprocessImageData: (imageData) =>
                new Promise((resolve) => {
                    // create a canvas element to handle the imageData
                    const canvas = document.createElement('canvas');
                    canvas.width = imageData.width;
                    canvas.height = imageData.height;
                    const ctx = canvas.getContext('2d');
                    ctx.putImageData(imageData, 0, 0);

                    // only draw image where we render our circular mask
                    ctx.globalCompositeOperation = 'destination-in';

                    // draw our circular mask
                    ctx.fillStyle = 'black';
                    ctx.beginPath();
                    ctx.arc(
                        imageData.width * 0.5,
                        imageData.height * 0.5,
                        imageData.width * 0.5,
                        0,
                        2 * Math.PI
                    );
                    ctx.fill();

                    // returns the modified imageData
                    resolve(
                        ctx.getImageData(0, 0, canvas.width, canvas.height)
                    );
                }),
        },
    });
</script>

postprocessImageBlob

Run postprocessing on the image blob, for example to convert an image to a format that isn't natively supported by the browser. For example to save GIF images

createDefaultImageScrambler

Creates the default image scrambler that is used with the imageScrambler property for created redacted images.

The default image scrambler first scales down the original image to create a mosaic effect, it then scrambles the pixels by offsetting them randomly, and finally it applies a blur. These steps prevent de-blurring the image and recovering the redacted information.

Export Default value Description
scrambleAmount
2
The amount to scramble the image pixels before blurring.
blurAmount
6
The amount of blur to apply to the scrambled image.

createDefaultShapePreprocessor

Creates the default shape preprocessor used for parsing lineEnd styles and frame styles.

LineStart and LineEnd style preprocessors

LineStart and LineEnd style preprocessors process shapes that have the lineStart or lineEnd property set to one of the following values.

Style Description
'none'
Don't render a decorative shape
'bar'
Render a bar.
'arrow'
Renders an open arrow.
'arrow-solid'
Renders a solid arrow.
'circle'
Render a open circle.
'circle-solid'
Renders a solid circle.
'square'
Render a open square.
'square-solid'
Renders a solid square.

Frame style preprocessors

Frame style preprocessors process shapes that have the frameStyle property set to one of the following values.

Style Description
'solid'
Renders a solid border around the crop.
'hook'
Renders corners in hook of the crop.
'line'
Renders a line alongside the edge of the crop.
'edge'
Renders a separate line alongside each edge of the crop.
'nine'
Renders 9-slice frames, pass image with frameImage property.
'polaroid'
Renders the image inside a classic polaroid.

Depending on the frame style additional properties can be set to finetune the look and feel of the frame.

Property Description
frameColor Determines the color of the frame. Defaults to [1, 1, 1].
frameInset Determines the distance between the crop edge and the line. Only available for 'line', 'edge' and 'hook' frame styles. Value should be set to a percentage. Defaults to '2.5%'.
frameOffset Determines the distance between the lines when using the 'line' frame style. Determines the draw offset from the intersecting edge when using the 'edge' frame style. Value should be set to a percentage. Defaults to '5%'.
frameAmount Determines how many lines are drawn when using the 'line' frame. Value should be set to a number. Defaults to 1.
frameSize Determines the width of the frame. Value should be set to a percentage. Defaults to '0.25%'.
frameLength Determines the length of the hook lines when using the 'hook' frame style. Value should be set to a percentage. Defaults to '2.5%'.
frameRadius Determines the corner radius of the frame. Only available on 'solid' and 'line' frame styles. Value should be set to a percentage. Defaults to 0.
frameImage The image used in the 'nine' frameStyle.
frameSlices An object describing the positions of the slices used to select images for each part of the 9-slice image frame.

frameSlices

The coordinates set to the frameSlices property below describe 4 slices inside an image (see visual below code snippet).

They are set to values between 0 and 1, .2 in the example below means the slice will be positioned at 20% offset from the frameImage width.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        imageFrame: {
            frameStyle: 'nine',
            frameImage: 'my-frame.png',
            frameSlices: {
                x1: 0.2, // red
                y1: 0.2, // green
                x2: 0.8, // blue
                y2: 0.8, // yellow
            },
        },
    });
</script>

As we can see in the image below the 4 slices result in 9 individual images which Pintura will automatically assign to the correct frame shapes.

x1 x2 y1 y2

createShapePreprocessor

Accepts a shape processor array and returns a function that can be assigned to the editor shapePreprocessor property.

The single parameter should be an array of functions. Each function receives the inputShape and an options object. The function can then return an array of shapes or undefined if it can't process the shape.

If the function can preprocess the shape it should then make sure it doesn't preprocess the shape twice, in the example below this means removing the style property from the output shape.

The option object contains a property called isPreview which is set to true when rendering the preview image and is set to false when rendering the output image. It also contains the current flipX, flipY, and rotation state and visual scale of the image.

// Array of shape preprocessors
[
    (inputShape, options) => [
        outputShape,
        outputShape,
        outputShape /* more shapes ...*/,
    ],
    (inputShape, options) => [outputShape],
    // ... another processor here
];

In the example below we pick up shapes that have a custom style property. If it's set to 'white' we apply a white backgroundColor.

import {
    openDefaultEditor,
    createDefaultFrameStyles,
    createDefaultLineEndStyles,
    createShapePreprocessor,
    createLineEndProcessor,
    createFrameStyleProcessor,
} from './pintura.js';

openDefaultEditor({
    src: './my-image.jpeg',

    // Add a square to the image with a custom `style` property
    imageAnnotation: [
        {
            x: 0,
            y: 0,
            width: 200,
            height: 200,
            style: 'white',
        },
    ],

    // Set our custom shape preprocessor
    shapePreprocessor: createShapePreprocessor([
        // set default line end styles
        createLineEndProcessor(createDefaultLineEndStyles()),

        // set default frame styles
        createFrameStyleProcessor(createDefaultFrameStyles()),

        // our custom processor
        (shape, options) => {
            // Should return undefined if no match
            if (!shape.style) return;

            // Should then make sure it no longer matches after processing, here we remove the style property from the clone
            const { style, ...clone } = shape;

            // Make changes to the output shape
            if (style === 'white') clone.backgroundColor = [1, 1, 1];

            // Return new shapes
            return [clone];
        },
    ]),
});

Note that the shapeProcessor runs before rendering the shape to the screen and before rendering the shape to the output image, it doesn't modify the original shape data.

In the example above this means that the new backgroundColor value won't be reflected in the editor style controls. We can use shape.disableStyle to disable style controls.

createDefaultFrameStyles

export to generate the default frame style object.

createDefaultLineEndStyles

export to generate the default line end styles object.

createFrameStyleProcessor

export to merge custom frame styles with the default frame styles.

createLineEndProcessor

export to merge custom line end styles with the default line end styles.

processImage

Use the processImage function to generate images without loading the editor interface.

import {
    processImage,
    createDefaultImageReader,
    createDefaultImageWriter,
} from './pintura.js';

const res = await processImage('./my-image.jpeg', {
    imageReader: createDefaultImageReader(),
    imageWriter: createDefaultImageWriter(),
    imageCrop: {
        x: 64,
        y: 64,
        width: 512,
        height: 512,
    },
    imageRotation: 0.25,
});

console.log(res);
// logs: { src:…, dest:… , imageState:…, store:… }

legacyDataToImageState

Converts legacy v6 data objects to imageState objects.

Needs the image size and a reference to the editor instance to correctly calculate the imageState.

const editor = openDefaultEditor({
    src: 'my-image.jpeg',
});

editor.on('load', ({ size }) => {
    editor.imageState = legacyDataToImageState(editor, size, legacyDataObject);
});