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.
Dimensions | Format | Pixel Data |
---|---|---|
width | colorSpace | data |
height | colorType π§ͺ | |
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
ImageData
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'})
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///...')