Skip to main content

ImageData

The ImageData object offers a convenient container that bundled raw pixel data with metadata helpful for working with it. Skia Canvas's implementation of the class mirrors the standard ImageData's structure and behavior, but extends it in a few ways.

DimensionsFormatPixel Data
widthcolorSpacedata
heightcolorType πŸ§ͺ
bytesPerPixel πŸ§ͺ

Working with ImageData objects​

Empty ImageData objects can be created either by calling the context's createImageData() method or the new ImageData() constructor:

let id = ctx.createImageData(800, 600)

or, equivalently:

let id = new ImageData(800, 600)

Choosing a colorType​

By default ImageData represents bitmaps using an rgba ordering of color channels in subsequent bytes of the buffer, but there are quite a few other ways of arranging pixel data to choose from. You can specify one by passing an optional settings object with a colorType field when creating the object:

let bgraData = new ImageData(128, 128, {colorType:'bgra'})

See below for a list of supported colorType formats.

Manipulating pixels​

Once you've created an ImageData you can access its buffer through its data attribute (here using the default rgba color type):

// you can read pixel values out…
let firstPixel = id.data.slice(0, 4)
let [r, g, b, a] = firstPixel

// …or write to them, here setting the entire buffer to #F00
for (let i=0; i<id.data.length; i+=id.bytesPerPixel) {
imageData.data[i + 0] = 255 // red
imageData.data[i + 1] = 0 // green
imageData.data[i + 2] = 0 // blue
imageData.data[i + 3] = 255 // alpha
}

Drawing to the Canvas​

According to the standard, the only way to draw ImageData to a canvas is through the putImageData() method, which copies either the entire ImageData or a rectangle within it to the canvas, pixel-for-pixel. Since this is copying rather than drawing, the operation ignores the current context state, including any transformations, filter, or global opacity options that have been set.

Skia Canvas, however, allows you to ImageData and Image objects interchangably when dealing with the canvas. If you pass an ImageData to the drawImage() method, its contents will be drawn to the canvas while honoring the context settings that are ignored by putImageData(). You may also pass ImageData objects to the createPattern() method.

Constructor​

// create an empty buffer filled with transparent pixels
new ImageData(width, height)
new ImageData(width, height, {colorType='rgba', colorSpace='srgb'})

// copy an existing buffer into an ImageData container
new ImageData(buffer, width)
new ImageData(buffer, width, height)
new ImageData(buffer, width, height, {colorType='rgba', colorSpace='srgb'})

new ImageData(image_data) // create a copy from another ImageData
new ImageData(image, {colorType, colorSpace}) // decode the pixels from a bitmap Image
returns β†’ ImageData
note

The optional colorSpace value can currently only be set to "srgb" (the default value), but this will hopefully change to include wider gamuts like "display-p3" in the future. For now you can simply omit it and use the default sRGB colorspace.

When creating an empty ImageData you must fully specify the dimensions in order to determine the size of the resulting buffer (in conjunction with the colorType). In cases where you already have a Buffer object, you only need to provide the width so it knows where to β€˜wrap’ the linear buffer. When passing an existing ImageData or Image object to the constructor the dimensions are known, but you can specify a non-default colorType you'd like to decode to in the Image case.

Properties​

.width & .height​

The dimensions of the ImageData cannot be changed after it is created. These properties give you read-only access to the 2D dimensions of the image.

.colorType​

The colorType value describes the layout of bytes within the buffer and how their values map onto the different components of each pixel. The most common formats devote 1 byte to each channel, with each pixel containing 4 channels in various orders. These formats have been given aliases for convenience:

// aliases for the most common 4-byte formats
"rgb" // for RGB888x
"rgba" // for BGRA8888
"bgra" // for BGRA8888

There are many other options with more verbose names (see this listing for descriptions of each):

// 1 byte per pixel
"Alpha8", "Gray8", "R8UNorm"

// 2 bytes per pixel
"A16Float", "A16UNorm", "ARGB4444", "R8G8UNorm", "RGB565"

// 4 bytes per pixel
"RGB888x", "RGBA8888", "BGRA8888", "BGR101010x", "BGRA1010102",
"R16G16Float", "R16G16UNorm", "RGB101010x", "RGBA1010102",
"RGBA8888", "SRGBA8888"

// 8 bytes per pixel
"R16G16B16A16UNorm", "RGBAF16", "RGBAF16Norm"

// 16 bytes per pixel
"RGBAF32"

Note that not all of them use 4-byte orderings like rgba does, so be sure to use the .bytesPerPixel field when stepping through them.

.bytesPerPixel​

An integer describing the byte-size of the ImageData's pixels given its colorType.

let id = new ImageData(10, 10)
console.log(id.data.length == id.width * id.height * id.bytesPerPixel) // β†’ true

.data​

A writeable buffer with the pixel contents of the image presented as an array of 8-bit bytes. See the standard docs for more details.

loadImageData()​

loadImageData(src, width)
loadImageData(src, width, height)
loadImageData(src, width, height, {colorType='rgba'})
returns β†’ Promise<ImageData>

Similar to the loadImage() utility, loadImageData() will asynchronously fetch a URL or local file path and package it into a usable object for you. In this case, you will need to provide slightly more information about the nature of the data since you will be loading β€˜raw’ binary data lacking an internal representation of its dimensions or color type. If the file you are loading is stored in rgba format, you need only specify the row-width of the image.

If the data uses a non-standard color type you'll need to fully specify the dimensions and colorType:

import {loadImageData} from 'skia-canvas'

let id = await loadImageData('https://skia-canvas.org/icon.raw', 64, 64, {colorType:'bgra'})

Note that in addition to HTTP URLs you may also call loadImageData() using Data URLs. Just make sure you use the mime type application/octet-stream in the header:

await loadImageData('data:application/octet-stream;base64,//8A////AP///...')