Skip to content

Getting Started

Installation

Install from npm:

shell
npm i @alxcube/lens

To use in node you will need Jimp library and Lens-Jimp adapter:

shell
npm i jimp @alxcube/lens-jimp

Import

Browser

Lens is distributed in ES module format and in UMD format.

If you are using bundler, you can import library components from @alxcube/lens:

ts
import { distort } from "@alxcube/lens";

If not using bundlers, you can import directly from Lens ES module:

js
import { distort } from "path/to/lens.js";

Or you can load UMD version, so lens will be available in global namespace as 'lens':

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript" src="path/to/lens.umd.cjs"></script>
    <script>
      console.log(lens.VERSION);
      const image = lens.Canvas.createFromUrl("path/to/image.png").then(
        (image) => lens.distort(image, "Arc", [90])
      );
      // ...
    </script>
  </body>
</html>

Node.js

Lens can be imported in Node as ES module and as CommonJS module:

js
import { distort } from "@alxcube/lens";
js
const { distort } = require("@alxcube/lens");

Usage

Hello World

Here is basic example of how you can use lens to distort image using Arc distortion:

ts
import { Canvas, distort, toHTMLCanvasElement } from "@alxcube/lens";

// create image adapter for source image
const image = await Canvas.createFromUrl("path/to/source-image.png");

// distort image
const distortionResult = await distort(image, "Arc", [180]);

// get underlying OffscreenCanvas
const canvas = distortionResult.image.getResource();

// convert OffscreenCanvas to HTMLCanvasElement to be able to insert it in DOM
const canvasElement = toHTMLCanvasElement(canvas);

// display result
document.body.appendChild(canvasElement);
js
import { Adapter } from "@alxcube/lens-jimp";
import { distort } from "@alxcube/lens";

// create image adapter for source image
const image = await Adapter.createFromFile("path/to/image.png");

// distort image
const distortionResult = await distort(image, "Arc", [180]);

// get underlying Jimp instance
const jimpImage = distortionResult.image.getResource();

// save result
jimpImage.write("path/to/result.png");

Passing image resources directly to distort()

In previous example we used adapter static methods for image adapter creation. But you can pass image resources directly to distort() function. Internally they will be wrapped in corresponding adapter interface.

In browser, you can pass instance of HTMLCanvasElement or OffscreenCanvas to distort().

INFO

Underlying resource type of result image matches that of source image. That means, if you pass HTMLCanvasElement to distort(), result image getResource() method will also return instance of HTMLCanvasElement. And if you pass OffscreenCanvas, result resource will be OffscreenCanvas too.

ts
import { distort, preloadHtmlImage } from "@alxcube/lens";

// load image by url
const image: HTMLImageElement = await preloadHtmlImage("path/to/image.png");

// draw image on canvas
const canvas: HTMLCanvasElement = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);

// distort image
const result = await distort(canvas, "Arc", [180]);

To make such approach work in Node, you should import @alxcube/lens-jimp for side effect. It will register Jimp adapter factory in Lens ImageAdapter factories pool, and then you will be able to pass Jimp instances to distort() function. This only need to be done once, so you can put this import somewhere in your app initialization module.

js
import "@alxcube/lens-jimp"; // import for side effect
import jimp from "jimp";
import { distort } from "@alxcube/lens";

// load image file
const image = await Jimp.read("path/to/image.png");

// distort image
const result = await distort(image, "Arc", [180]);

Distortion Result

The distort() function returns DistortionResult interface, which is plain object with following fields:

  • image - ImageAdapter interface object with distorted image.
  • distortion - ReversePixelMapper interface instance, which was used for distortion. You can use it for inspecting specific distortion coefficients, calculated internally, or for reusing for similar distortion of other image, since distort() also accepts ReversePixelMapper instance instead distortion name and distortion arguments.
  • startTimestamp - timestamp of distortion processing start.
  • endTimestamp - timestamp of distortion processing end.
  • duration - duration of distortion process in milliseconds.
  • weightLookupTable - this property is added only if EWA resampling was used, and contains color weight values, calculated by resample filter. It is unlikely that you ever need this property.

ImageAdapter in distortion result holds image virtual viewport which is required for correct composition of multiple distorted images, or may be used for further image distortions. If all this stuff is redundant for your use case, you can replace distort() function to distortUnwrap(), which accepts same arguments, but returns unwrapped underlying image resource:

ts
import { distortUnwrap } from "@alxcube/lens";

const image = new OffscreenCanvas(100, 100);

// ... draw something on canvas

// distort image and get distorted image canvas
const resultOffscreenCanvas = await distortUnwrap(image, "Arc", [180]);

// this is equal to:
// const { image: resultImage } = await distort(image, "Arc", [180]);
// const resultOffscreenCanvas = await resultImage.getResource();