Skip to content

Latest commit

 

History

History

pixel

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

@thi.ng/pixel

npm (scoped) npm downloads Twitter Follow

This project is part of the @thi.ng/umbrella monorepo.

About

screenshot

Typed array backed, packed integer pixel buffers with customizable layout formats and the following operations:

  • Buffer creation from HTML image elements w/ opt resize & format conversion (browser only)
  • Buffer-to-buffer blitting w/ automatic format conversion
  • Buffer-to-canvas blitting
  • Buffer-to-buffer blending w/ Porter-Duff operators
  • Pre/post-multiply alpha
  • Region / sub-image extraction
  • Single-channel manipulation / extraction / replacement / conversion
  • Inversion
  • XY pixel accessors
  • 10 preset formats (see table below)
  • Declarative custom format & optimized code generation
  • HTML canvas creation & ImageData utilities

WIP features

  • Accessors for normalized channel value
  • Pre/Post-multipy (only if alpha is available)
  • Re-add strided float buffers / formats
  • Readonly texture sampling abstraction
    • Wrap-around behaviors
    • Filtered access (bilinear interpolation)

Preset pixel formats

All packed integer formats use the canvas native ABGR 32bit format as common intermediate for conversions. During conversion to ABGR, channels with sizes smaller than 8 bits will be scaled appropriately to ensure an as full-range and as linear as possible mapping. E.g. a 4 bit channel will be scaled by 255 / 15 = 17.

Format specs can freely control channel layout within current limits:

  • Channel sizes: 1 - 32 bits.
  • Storage: 8, 16 or 32 bits per pixel
Format ID Bits per pixel Description
ALPHA8 8 8 bit channel (alpha only)
GRAY8 8 8 bit single channel (grayscale conv)
GRAY_ALPHA8 16 8 bit single channel (grayscale conv), 8 bit alpha
GRAY16 16 16 bit single channel (grayscale conv)
GRAY_ALPHA16 32 16 bit single channel (grayscale conv), 16 bit alpha
ARGB4444 16 4 channels @ 4 bits each
ARGB1555 16 5 bits each for RGB, 1 bit alpha
RGB565 16 5 bits red, 6 bits green, 5 bits blue
RGB888 32 (24 effective) 3 channels @ 8 bits each
ARGB8888 32 4 channels @ 8 bits each
BGR888 32 (24 effective) 3 channels @ 8 bits each
ABGR8888 32 4 channels @ 8 bits each
  • ALPHA8 is mapped from/to ABGR alpha channel
  • GRAY8/16, GRAY_ALPHA8/16 compute grayscale/luminance when converting from ABGR and in return produce grayscale ABGR
  • In all built-in formats supporting it, the alpha channel always occupies the most-significant bits (up to format size)

Installation

yarn add @thi.ng/pixel

Dependencies

Usage examples

Porter-Duff operators:

Live demo | Source

porter-duff compositing modes

Code for the screenshot at the top of this readme...

Also see full example here:

Live demo | Source

import * as pix from "@thi.ng/pixel";
import { SRC_OVER_I } from "@thi.ng/porter-duff";

import IMG from "../assets/haystack.jpg";
import LOGO from "../assets/logo-64.png";

Promise
    .all([IMG, LOGO].map(pix.imagePromise))
    .then(([img, logo]) => {

        // init 16 bit packed RGB pixel buffer from image (resized to 256x256)
        const buf = pix.PackedBuffer.fromImage(img, pix.RGB565, 256, 256);

        // create grayscale buffer for logo and use Porter-Duff operator to
        // composite with main image. Since the logo has transparency, we need
        // to premultiply alpha first...
        pix.PackedBuffer.fromImage(logo, pix.GRAY_ALPHA88)
            .premultiply()
            .blend(SRC_OVER_I, buf, {
                dx: 10,
                dy: 10
            });

        // extract sub-image
        const region = buf.getRegion(32, 96, 128, 64);
        // copy region back at new position
        region.blit(buf, { dx: 96, dy: 32 });

        // or alternatively blit buf into itself
        // buf.blit(buf, { dx: 96, dy: 32, sx: 32, sy: 96, w: 128, h: 64 });

        // create html canvas
        // (returns obj of canvas & 2d context)
        const ctx = pix.canvas2d(buf.width, buf.height * 3);

        // write pixel buffer to canvas
        buf.blitCanvas(ctx.canvas);

        // manipulate single color channel (here red)
        const id = 0;
        // obtain channel & invert
        const ch = buf.getChannel(id).invert();
        // create dot pattern
        for (let y = 0; y < ch.height; y += 2) {
            for (let x = (y >> 1) & 1; x < ch.width; x += 2) {
                ch.setAt(x, y, 0xff);
            }
        }
        // replace original channel
        buf.setChannel(id, ch);

        // write pixel buffer to new position
        buf.blitCanvas(ctx.canvas, 0, buf.height);

        // create & write grayscale version
        buf.as(GRAY8).blitCanvas(ctx.canvas, 0, buf.height * 2);

        document.body.appendChild(ctx.canvas);
});

API

TODO see examples & source comments for now

Authors

  • Karsten Schmidt

License

© 2019 Karsten Schmidt // Apache Software License 2.0