1. T. Michael Keesey
  2. pictish



by T. Michael Keesey (keesey@gmail.com)

Pictish is a collection of TypeScript/JavaScript functions for processing image data.

(It is also an obscure extinct language from Scotland.)


Pictish is available under the MIT license. For more details, see the LICENSE file.

Important Files

  • bin/pictish.js: Pictish as a JavaScript file.
  • bin/pictish.min.js: A minified version of pictish.js.
  • build.sh: UNIX shell script to build the JavaScript files from TypeScript source. Requires Java and the TypeScript compiler.


Pictish requires certain HTML5 features which are not available in all browsers:

  • <canvas> elements
  • Typed arrays

Compiling Pictish requires the TypeScript compiler, although compiled JavaScript versions are included in the repository.

Using Pictish

You can use Pictish functions in your TypeScript or JavaScript projects. To include the script in a web page, download pictish.js or pictish.min.js and include a tag like this;

<script type="text/javascript" src="PATH_TO_SCRIPTS/pictish.min.js"></script>

Creating Image Data

function createImageData(width: number, height: number, fill?: RGBA): ImageData;

An ImageData object has the following properties:

  • data: an array of bytes (type Uint8ClampedArray or CanvasPixelsArray, depending on browser) storing color data. Each pixel uses four bytes, indicating the red, green, blue, and alpha values, respectively.
  • width: the width, in pixels
  • height: the height, in pixels

An RGBA object has the properties r, g, b, and a, indicating the red, green, blue, and alpha values, respectively. (Each ranges from 0 to 255.) If the fill argument is omitted, the image data will be set to transparent black (all zeroes).

If width or height are not greater than or equal to one, this function returns null.

Example Usage

// empty 100×100 image
pictish.createImageData(100, 100);

// 320×240 image filled with red
pictish.createImageData(320, 240, { r: 0xFF, g: 0x00, b: 0x00, a: 0xFF });

// Render to a <canvas> element
canvas.getContext('2d').putImageData(imageData, 0, 0);

Reading Data from an Image File (or BLOB)

function fromFile(blob: Blob,
    resultHandler: (result: ImageData) => any,
    errorHandler?: (event: ErrorEvent) => any,
    progressHandler?: (event: ProgressEvent) => any
): void;

Example Usage

function readImage(blob)
    function handleError(event)
        alert("There was an error: " + event);

    function handleResult(imageData)
        alert("Loaded file.");

    pictish.fromFile(blob, handleResult, handleError);

Reading Data from an HTML Image

function fromHTMLImage(source: HTMLImageElement): ImageData;

Example Usage

<img id="myimage" src="myimage.png" width="320" height="240" alt="" />
<script type="text/javascript">
    var img = document.getElementById('myimage');
    var imageData = pictish.fromHTMLImage(img);


function crop(source: ImageData, area: Area): ImageData;

An Area object must have the fields: bottom, left, right, and top.

Example Usage

// Grab an image from the HTML.
var source = pictish.fromHTMLImage(document.getElementById('myimage'));

// Crop 10 pixels off all sides.
var area = {
    left: 10,
    right: source.width - 10,
    top: 10,
    bottom: source.height - 10
var cropped = pictish.crop(source, area);


function flipX(source: ImageData, channelFlags?: number = 15): ImageData;
function flipY(source: ImageData, channelFlags?: number = 15): ImageData;

The channelFlags argument specifies which of the red, green, blue, and alpha channels are used. Each channel is determined by a certain bit: red: lowest bit green: second-lowest bit blue: third-lowest bit alpha: fourth-lowest bit

A formula for determining the number:

channelFlags = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0)

Example Usage

// Grab an image from a file.
var source = pictish.readImage(file, handleResult);

function handleResult(imageData)
    var flippedX = pictish.flipX(imageData);
    // All channels.

    var flippedY = pictish.flipY(imageData);
    // All channels.

    var flippedXAlpha = pictish.flipX(imageData, 8);
    // Only contains alpha channel -- everything else will be set to zero (black).

Scaling Down

function scaleDown(source: ImageData, scale: number, channelFlags?: number = 15): ImageData;
function quarter(source: ImageData, channelFlags?: number = 15): ImageData;

The scaleDown() function scales an image down by a given factor, scale, where 0 <= scale <= 1. (Any value outside that range will throw an error.)

Calling quarter(imageData, channelFlags) is equivalent to calling scaleDown(imageData, 0.5, channelFlags), but faster.

Example Usage

// Grab an image from the HTML.
var source = pictish.fromHTMLImage(document.getElementById('myimage'));

// Resize to a standard dimension.
if (source.width >= 256 || source.height >= 256)
    var scale = (source.width >= source.height) ? (256 / source. width) : (256 / source. height);
    var standard = pictish.scaleDown(source, scale);

    // Create a thumbnail 64 pixels in width and/or height
    var thumbnail = pictish.quarter(pictish.quarter(standard));


function silhouettize(source: ImageData): ImageData;

This function will desaturate an image, preserving luminosity in the alpha channel. All other channels (red, green, and blue) will be set to zero (black). A "silhouettized" image may be overlaid on a white background to show a desaturated (that is, greyscale) version of the original.

This function will also crop the image to its content area by trimming off white margins. Thus, a "silhouettized" image is always the same size or smaller than the source image.

Example Usage

// Grab an image from the HTML.
var source = pictish.fromHTMLImage(document.getElementById('myimage'));

var silhouette = pictish.silhouettize(source);