ImageScript

repository·master·Indexed 20 days ago

https://github.com/matmen/imagescript

A zero-dependency JavaScript library for high-performance bitmap image manipulation. It supports decoding and encoding for PNG, JPEG, WebP, TIFF, and GIF, as well as SVG and vector font rendering. Key features include the Image class for pixel manipulation and geometric transformations, the GIF and Frame classes for animated image handling, and tools for color operations like hue shifting and brightness adjustment. Compatible with Node.js, Deno, and the browser.

Tokens
4.9K
Snippets
20
Records
24
Agent score
71%

What's inside imagescript

  1. Overview of ImageScript features

    master

    ImageScript is a zero-dependency JavaScript library for bitmap image manipulation. It is designed for high performance by using lower-level memory access, minimizing memory copying, and utilizing WebAssembly or native binaries for decoding and encoding tasks.

    Key capabilities include:

    • Decoding: Supports PNG (grayscale, RGB, indexed colors, with/without alpha), JPEG (grayscale, RGB, CMYK), TIFF, and GIF.
    • Rendering: Supports SVG rendering and vector font rendering.
    • Manipulation: Includes functions for crop, rotate, composite, and more.
    • Color Operations: Includes invert, hueShift, and color information functions like averageColor and dominantColor.
    • Encoding: Supports encoding images as PNG, JPEG, WEBP, and GIF.
  2. Work with GIFs using GIF and Frame classes

    master

    ImageScript provides specialized classes for handling animated GIFs.

    • Frame: Represents a single frame in a GIF. It extends Image and includes properties for duration, xOffset, yOffset, and disposalMode.
    • GIF: Extends Array<Frame> and represents the entire animation. It includes a loopCount property (-1 for unlimited).

    Key Operations:

    • Create a Frame from an Image: Use Frame.from(image, duration, xOffset, yOffset, disposalMode).
    • Encode a GIF: Call gifInstance.encode(quality) on a GIF instance to get a Uint8Array of the encoded data.
    • Decode a GIF: Use GIF.decode(data) to turn binary data into a GIF instance.

    Frame Disposal Modes:

    • Frame.DISPOSAL_KEEP: 'keep'
    • Frame.DISPOSAL_PREVIOUS: 'previous'
    • Frame.DISPOSAL_BACKGROUND: 'background'
    // Decoding a GIF
    const gif = await GIF.decode(buffer);
    
    // Creating a new GIF from frames
    const frame1 = Frame.from(img1, 100);
    const frame2 = Frame.from(img2, 100);
    const myGif = new GIF([frame1, frame2], 0); // Loops once
    
    // Encoding to buffer
    const encodedData = await myGif.encode(90);
  3. Understand Frame disposal modes

    master

    When working with animations (specifically GIFs), frames can have a dispose property that determines how the next frame is rendered over the current one:

    • dispose: 'any' (or default): No specific instruction.
    • dispose: 'background' (mode 2): The frame is cleared to the background before the next frame is drawn.
    • dispose: 'none' (mode 0 or 1): The frame is drawn on top of the previous content without clearing.
  4. The Image class

    master

    The Image class is the core of ImageScript, representing an RGBA image. It provides a comprehensive API for pixel manipulation, geometric transformations, color adjustments, and encoding/decoding.

    Key Capabilities

    • Pixel Access: Get or set individual pixels using RGBA or integer color values.
    • Transformations: Resize, crop, rotate, flip, and apply effects like fisheye.
    • Drawing: Draw boxes, circles, and fill areas with solid colors or gradients.
    • Color Manipulation: Adjust brightness, saturation, hue, and opacity, or invert colors.
    • Encoding/Decoding: Convert images to/from PNG, JPEG, and WEBP formats.
    const { Image } = require('imagescript');
    
    // Create a new 100x100 image
    const img = new Image(100, 100);
    
    // Set a pixel at (10, 10) to red
    img.setPixelAt(10, 10, Image.rgbToColor(255, 0, 0));
    
    // Get the color at (10, 10)
    const color = img.getPixelAt(10, 10);
    // color is an integer representing RGBA
  5. Use the Frame class

    master

    A Frame represents a single temporal slice of an animation. It contains an Image and metadata like timestamp and dispose mode.

    • constructor(width, height, buffer): Creates a frame. The buffer can be a raw buffer or an existing Image instance.
    • static from(framebuffer): Creates a frame from a framebuffer object (which must have width, height, and u8 or buffer).
    • clone(): Returns a new Frame with a cloned image and copied metadata.
    const { Frame } = require('imagescript/v2');
    
    // Creating a frame from an existing image
    const frame = new Frame(img.width, img.height, img.u8);
    frame.timestamp = 100;
    frame.dispose = 'background';
  6. Create and encode GIFs using gif_encoder

    master

    The gif_encoder class is used to build animated GIFs frame by frame. You instantiate it with the target width and height, add frames using the add method, and finally call finish to generate the encoded Uint8Array.

    const encoder = new gif_encoder(100, 100);
    
    // Add frames
    encoder.add(frame1Buffer, {
      width: 100,
      height: 100,
      delay: 100,
      dispose: 'none'
    });
    
    encoder.add(frame2Buffer, {
      width: 100,
      height: 100,
      delay: 150,
      dispose: 'any'
    });
    
    // Finalize the GIF
    const gifBuffer = encoder.finish({
      repeat: 0,
      comment: 'My Animation',
      application: 'ImageScript'
    });
  7. Render Text to an Image

    master

    Use Image.renderText to create an Image from a font buffer and text string. This method supports custom text layouts via the TextLayout class.

    Parameters:

    • font: A Uint8Array containing the TrueType (ttf/ttc) or OpenType (otf) font buffer.
    • scale: The font size.
    • text: The string to render.
    • color: (Optional) Hexadecimal color (default 0xffffffff).
    • layout: (Optional) An instance of TextLayout to control wrapping and alignment.
    const fontBuffer = fs.readFileSync('font.ttf');
    const layout = new TextLayout({ maxWidth: 500, wrapStyle: 'word' });
    const textImage = await Image.renderText(fontBuffer, 24, 'Hello World', 0xff0000ff, layout);
  8. Encode images using the PNG codec

    master

    The png interface provides methods to encode image data into the PNG format. You can use encode for synchronous encoding or encode_async for asynchronous encoding. Both methods require an ArrayBufferView of the image data and a png_encode_options object.

    // Example usage of the png interface
    const pngCodec: png = getPngCodec(); // implementation dependent
    const buffer: ArrayBufferView = getRawImageData();
    const options: png_encode_options = {
      width: 100,
      height: 100,
      compression: 'best',
      filter: 'paeth'
    };
    
    const pngData = pngCodec.encode(buffer, options);
    // OR
    const pngDataAsync = await pngCodec.encode_async(buffer, options);
  9. Decode PNG data

    master

    Use the decode function to parse a PNG-formatted Uint8Array and extract its pixel data.

    Parameters:

    • array: Uint8Array containing the PNG file data.

    Returns: An object containing:

    • width: number (image width).
    • height: number (image height).
    • buffer: Uint8Array containing the decoded pixel data. The buffer is normalized to 4 channels (RGBA) regardless of the original PNG color type.
    import { decode } from './png.mjs';
    
    const pngData = new Uint8Array([...]); // Valid PNG data
    const { width, height, buffer } = decode(pngData);
    console.log(`Decoded ${width}x${height} image`);
  10. Encode images using the WebP codec

    master

    The webp interface provides methods to encode image data into the WebP format via encode and encode_async. It accepts png_encode_options for configuration.

    const webpCodec: webp = getWebpCodec();
    const buffer: ArrayBufferView = getRawImageData();
    const options: png_encode_options = {
      width: 512,
      height: 512,
      quality: 0.9
    };
    
    const webpData = await webpCodec.encode_async(buffer, options);
  11. Decode image data with decode()

    master

    The top-level decode(data, onlyExtractFirstFrame) function is the primary entry point for turning binary data into an image object.

    • If the data is a GIF, it returns a GIF instance.
    • For other supported formats (PNG, JPEG, TIFF), it returns an Image instance.
    • onlyExtractFirstFrame: If true, the decoder stops after the first frame (useful for GIFs where you only need a thumbnail).
    const { decode } = require('imagescript');
    const image = await decode(buffer);
    // image is either an Image or a GIF instance