imagine.image
import imagine.image
imaginelifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelledimagine.image.*needsimport imagine.image.
Image: a raster image as an RGBA pixel buffer, and everything that
transforms one.
Resizing, cropping, rotation, compositing, colour adjustment and the named filters are all methods here. Every one produces a new image rather than altering the receiver, except where a method says otherwise.
Classes
Image
class imagine.Image < Canvas
A raster image: a rectangle of 8-bit RGBA pixels, everything that draws onto one, and everything that reshapes, filters or writes one out.
import imagine { Image, Color, LANCZOS }
Image.open('photo.jpg')
.thumbnail(400, 400, LANCZOS)
.save('thumb.webp')
Which operations copy and which do not
There is one rule, and it is worth learning because it is the only thing here that is not obvious:
- Anything that changes the image’s size returns a new
Image.resize(),crop(),rotate(),flip(),pad()and the rest leave the original untouched. - Everything else changes the image in place and returns it. Drawing, filters and compositing all work on the image you called them on, and return it so calls can be chained.
That means a chain mixing the two kinds still reads correctly, and
clone() is there for the times you want to keep the original before a
filter.
var original = Image.open('photo.jpg')
var small = original.thumbnail(200, 200) # original untouched
small.grayscale() # small is now grey
Memory
An image costs four bytes per pixel, so a 6000x4000 photograph is 96 MB in memory however small its file was. Reach for [[imagine.formats.probe]] before opening anything whose size you do not control.
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
imagine.Image(width: number, height: number, fill)
Creates a new image.
The image starts fully transparent unless a fill colour is given.
Parameters
width(number) — At least 1.height(number) — At least 1.fill(?Color|string|number) — A colour to fill with - Default: transparent.
Raises BoundsError When either dimension is below 1.
Image.open()
imagine.Image.open(source, options) -> Image
Opens an image file.
The format is detected from the file’s contents, not its name, so a mislabelled file still opens correctly.
JPEGs carrying an EXIF orientation tag are rotated upright, since that
is what the photograph was meant to look like and almost never what the
raw pixels are. Pass { orient: false } to get the pixels exactly as
stored.
Parameters
source(string|file) — A path, or an already-open file.options(?dict) —orient(bool, default true),format(string).
Returns Image
Raises DecodeError When the file is not a readable image.
Image.decode()
imagine.Image.decode(data: bytes, options) -> Image
Decodes image data held in memory.
The format is detected from the data unless format says otherwise, in
which case a file that is not really that format fails loudly rather
than being decoded as whatever it actually is.
Parameters
data(bytes)options(?dict) —orient(bool, default true),format(string).
Returns Image
Raises DecodeError When the data is not a readable image.
Image.from_pixels()
imagine.Image.from_pixels(width, height, pixels, format) -> Image
Wraps an existing RGBA pixel buffer as an image.
The buffer is adopted, not copied, so whatever produced it must not keep writing to it. Pixels run red, green, blue, alpha with straight (not premultiplied) alpha and no row padding.
Parameters
width(number)height(number)pixels(bytes) — Exactlywidth * height * 4bytes.format(?string) — The format these pixels were decoded from, recorded as metadata - Default: nil.
Returns Image
Image.size()
imagine.Image.size() -> dict
The image’s dimensions as {width, height}.
Returns dict
Image.format()
imagine.Image.format() -> ?string
The format this image was decoded from, or nil for one created in
memory.
This records where the image came from and never constrains where it can go; a PNG can always be saved as a JPEG.
Returns ?string
Image.set_format()
imagine.Image.set_format(format)
Records which format this image should be considered to have come from.
The only thing this changes is what encode() and save() write when
no format is given. It is set for you when an image is decoded; setting
it by hand is for pixels that arrived some other way and whose origin
you happen to know.
Parameters
format(?string) — A format name, or nil to clear it.
Returns — self
Image.bounds()
imagine.Image.bounds() -> dict
The rectangle covering the whole image, as {x, y, width, height}.
Returns dict
Image.is_opaque()
imagine.Image.is_opaque() -> bool
true when every pixel is fully opaque.
This walks the alpha channel, so it costs a pass over the image. Worth knowing before choosing an output format: an opaque image loses nothing as a JPEG.
Returns bool
Image.info()
imagine.Image.info() -> dict
A summary of the image as a dictionary holding width, height,
format, pixels (the count, not the buffer) and opaque.
Returns dict
Image.clone()
imagine.Image.clone() -> Image
An independent copy of the image, sharing nothing with it.
Returns Image
Image.layer()
imagine.Image.layer(fill) -> Image
A new image of the same size, fully transparent.
The usual way to build up a composite: draw onto the layer, then bring
it back with draw_image() under whichever blend mode and opacity the
effect calls for.
Parameters
fill(?Color|string|number) — A colour to fill with - Default: transparent.
Returns Image
Image.resize()
imagine.Image.resize(width, height, filter) -> Image
Returns the image resampled to an exact size.
The aspect ratio is not preserved; the result is exactly the size asked
for. Use thumbnail() or cover() when the proportions matter.
Parameters
width(number) — At least 1.height(number) — At least 1.filter(?string) — A resampling filter - Default:LANCZOS.
Returns Image
Raises BoundsError When either dimension is below 1.
Image.scale()
imagine.Image.scale(factor: number, filter) -> Image
Returns the image resampled by a factor, keeping its proportions.
Parameters
factor(number) — Greater than zero. 0.5 halves each side.filter(?string) — A resampling filter - Default:LANCZOS.
Returns Image
Image.thumbnail()
imagine.Image.thumbnail(max_width, max_height, filter) -> Image
Returns the image shrunk to fit inside a box, keeping its proportions.
The result is no larger than the box in either direction, and usually smaller in one. An image that already fits is returned at its original size rather than enlarged, which is what makes this the right call for thumbnails: enlarging a small image to fill a thumbnail box only makes it blurry.
Parameters
max_width(number)max_height(number)filter(?string) — A resampling filter - Default:LANCZOS.
Returns Image
Image.fit()
imagine.Image.fit(width, height, filter) -> Image
Returns the image scaled to fit inside a box, keeping its proportions, enlarging it if it is smaller than the box.
The difference from thumbnail() is exactly that: this one will scale
up.
Parameters
width(number)height(number)filter(?string) — A resampling filter - Default:LANCZOS.
Returns Image
Image.cover()
imagine.Image.cover(width, height, options) -> Image
Returns the image filling a box exactly, keeping its proportions by cropping whatever overflows.
This is what a CSS background-size: cover does, and what almost every
avatar or card thumbnail wants: the box is filled edge to edge with no
distortion and no letterboxing, at the cost of losing some of the image.
Parameters
width(number)height(number)options(?dict) —anchor(where the kept part comes from, defaultCENTER),filter.
Returns Image
Image.contain()
imagine.Image.contain(width, height, options) -> Image
Returns the image fitted inside a box exactly, keeping its proportions by padding whatever is left over.
The counterpart to cover(): nothing is lost, but the result has bars
on two sides.
Parameters
width(number)height(number)options(?dict) —background(the padding colour, default transparent),anchor(defaultCENTER),filter.
Returns Image
Image.crop()
imagine.Image.crop(x, y, width, height) -> Image
Returns a rectangular region of the image.
The rectangle must lie entirely inside the image. Clamping a crop that
runs off the edge would hand back different dimensions than were asked
for, which is a worse surprise than an error; use pad() first if the
region really is meant to extend past the edge.
Parameters
x(number)y(number)width(number)height(number)
Returns Image
Raises BoundsError When the rectangle does not fit inside the
image.
Image.trim()
imagine.Image.trim(options) -> Image
Returns the image with a uniform border trimmed away.
The border colour is taken from the top-left pixel unless background
names one. tolerance is how far a pixel may differ from it and still
count as border, measured as the largest difference across the four
channels.
An image that is entirely border is returned as a 1x1 image rather than an empty one, since an image with no pixels is not a thing this module can represent.
Parameters
options(?dict) —background,tolerance(default 0).
Returns Image
Image.pad()
imagine.Image.pad(top, right, bottom, left, background) -> Image
Returns the image with a border added on each side.
Negative amounts are not accepted; use crop() to remove edges.
Parameters
top(number)right(?number) — Default: the same as top.bottom(?number) — Default: the same as top.left(?number) — Default: the same as right.background(?Color|string|number) — Default: transparent.
Returns Image
Image.rotate()
imagine.Image.rotate(degrees: number, background) -> Image
Returns the image rotated by an angle in degrees, clockwise.
Quarter turns are exact and lossless. Any other angle resamples the
pixels and grows the canvas to hold the rotated corners, filling the
gaps with background.
Parameters
degrees(number)background(?Color|string|number) — The colour behind the corners- Default: transparent.
Returns Image
Image.rotate_90()
imagine.Image.rotate_90() -> Image
Returns the image turned a quarter turn clockwise. Lossless.
Returns Image
Image.rotate_180()
imagine.Image.rotate_180() -> Image
Returns the image turned upside down. Lossless.
Returns Image
Image.rotate_270()
imagine.Image.rotate_270() -> Image
Returns the image turned a quarter turn anticlockwise. Lossless.
Returns Image
Image.flip()
imagine.Image.flip(mode) -> Image
Returns the image mirrored.
Parameters
mode(?number) —FLIP_HORIZONTAL,FLIP_VERTICALorFLIP_BOTH- Default:
FLIP_HORIZONTAL.
- Default:
Returns Image
Image.flip_horizontal()
imagine.Image.flip_horizontal() -> Image
Returns the image mirrored left to right.
Returns Image
Image.flip_vertical()
imagine.Image.flip_vertical() -> Image
Returns the image mirrored top to bottom.
Returns Image
Image.transpose()
imagine.Image.transpose() -> Image
Returns the image reflected across its main diagonal, so a w x h image
becomes h x w.
Returns Image
Image.apply_lut()
imagine.Image.apply_lut(red, green, blue, alpha)
Rewrites every pixel through up to four 256-entry lookup tables, one per channel.
This is the primitive behind most of the adjustments below, and it is the fastest way to apply any per-channel tone curve: the table is built once whatever the image’s size, and applying it is a single indexed load per channel.
A nil table leaves that channel alone. Tables are built with the
helpers in [[imagine.filters]], or with [[imagine.filters.build_lut]]
for a curve of your own.
Parameters
red(?bytes) — A 256-entry table, or nil.green(?bytes)blue(?bytes)alpha(?bytes)
Returns — self
Image.apply_matrix()
imagine.Image.apply_matrix(matrix)
Rewrites every pixel through a 4x5 colour matrix.
The matrix is a flat list of 20 numbers, laid out row by row, and is the same shape SVG and CSS filters use. The last entry of each row is a constant added afterwards, in 0-255 units.
r' = m0*r + m1*g + m2*b + m3*a + m4
g' = m5*r + m6*g + m7*b + m8*a + m9
b' = m10*r + m11*g + m12*b + m13*a + m14
a' = m15*r + m16*g + m17*b + m18*a + m19
Applying several matrices in a row is both slower and less accurate than combining them with [[imagine.filters.combine_matrices]] and applying the result once.
Parameters
matrix(list) — 20 numbers.
Returns — self
Image.brightness()
imagine.Image.brightness(delta)
Adds a fixed amount to every colour channel.
Parameters
delta(number) — -255 to 255. Positive brightens.
Returns — self
Image.contrast()
imagine.Image.contrast(amount)
Pushes colours away from or toward mid-grey.
Parameters
amount(number) — -100 (flat grey) through 0 (unchanged) to 100 (hard black and white).
Returns — self
Image.gamma()
imagine.Image.gamma(gamma)
Applies a gamma curve, moving the midtones without touching black or white.
Parameters
gamma(number) — Greater than zero. Below 1 darkens, above 1 lightens.
Returns — self
Image.levels()
imagine.Image.levels(black, white, gamma)
Stretches a range of input values across the full scale.
The single most useful correction for a flat or washed-out photograph:
everything at or below black becomes black, everything at or above
white becomes white, and the rest is spread between them.
Parameters
black(number) — The input value that becomes black, 0-255.white(number) — The input value that becomes white, 0-255.gamma(?number) — A midtone curve to apply along the way - Default: 1.
Returns — self
Image.invert()
imagine.Image.invert()
Inverts the colour channels, producing a photographic negative.
Alpha is untouched, so a transparent image stays transparent rather than becoming opaque.
Returns — self
Image.threshold()
imagine.Image.threshold(level)
Forces every pixel to black or white by comparing its brightness against a threshold.
The image is converted to grey first, so the split is made on perceived brightness rather than on each channel separately.
Parameters
level(?number) — The cut, 0-255 - Default: 128.
Returns — self
Image.posterize()
imagine.Image.posterize(levels)
Reduces each channel to a fixed number of evenly spaced steps.
This flattens gradients into visible bands. For a reduction that picks
the colours to keep rather than spacing them evenly, use quantize().
Parameters
levels(number) — 2 or more.
Returns — self
Image.opacity()
imagine.Image.opacity(factor)
Scales the alpha channel, making the whole image more transparent.
The scaling is relative: applying 0.5 twice leaves a quarter of the original opacity, not half.
Parameters
factor(number) — 0 (invisible) to 1 (unchanged).
Returns — self
Image.grayscale()
imagine.Image.grayscale()
Converts the image to shades of grey.
Channels are weighted for perceived brightness, so a bright yellow comes out light and a deep blue comes out dark, which is what the eye expects.
Returns — self
Image.sepia()
imagine.Image.sepia()
Gives the image the warm brown cast of an old photograph.
Returns — self
Image.saturate()
imagine.Image.saturate(amount)
Scales the image’s saturation.
Parameters
amount(number) — 0 removes all colour, 1 leaves it alone, above 1 intensifies.
Returns — self
Image.hue_rotate()
imagine.Image.hue_rotate(degrees)
Rotates every hue around the colour wheel, leaving brightness and saturation alone.
Parameters
degrees(number)
Returns — self
Image.duotone()
imagine.Image.duotone(shadow, highlight)
Maps the image’s brightness onto a two-colour ramp.
Dark pixels take shadow, light ones take highlight, and everything
between is interpolated.
Parameters
shadow(Color|string|number)highlight(Color|string|number)
Returns — self
Image.tint()
imagine.Image.tint(color, amount)
Blends a flat colour into the image.
At an amount of 1 the image becomes that colour entirely; at 0.2 it takes on a wash of it. Alpha is untouched, so transparent areas stay transparent.
Parameters
color(Color|string|number)amount(?number) — 0 to 1 - Default: 0.5.
Returns — self
Image.colorize()
imagine.Image.colorize(color)
Converts to grey and then tints, producing a monochrome image in a single colour.
Parameters
color(Color|string|number)
Returns — self
Image.quantize()
imagine.Image.quantize(colors, dither)
Reduces the image to at most a given number of colours.
Unlike posterize(), the colours kept are chosen to suit the image
rather than spaced evenly, so a photograph survives far fewer of them.
Dithering trades visible banding for a fine stipple, which almost always
looks better at low colour counts.
This is also a preview of what GIF export will do, since GIF cannot hold more than 256 colours per frame.
Parameters
colors(?number) — 2 to 256 - Default: 256.dither(?bool) — Default: false.
Returns — self
Image.premultiply()
imagine.Image.premultiply()
Multiplies the colour channels by alpha.
imagine keeps straight alpha everywhere, so this is for handing pixels
to something that expects them premultiplied. It loses precision in
near-transparent pixels and cannot be perfectly undone.
Returns — self
Image.unpremultiply()
imagine.Image.unpremultiply()
Undoes premultiply(), as far as 8 bits allow.
Returns — self
Image.convolve()
imagine.Image.convolve(kernel, options)
Applies a convolution kernel to the image.
The kernel is a flat list of size * size numbers with an odd size.
The default divisor of 0 means “divide by the kernel’s own sum”, which
is what nearly every published kernel expects; pass an explicit divisor
for the ones whose weights sum to zero.
Alpha goes through the kernel along with the colour channels unless
keep_alpha says otherwise, so blurring a shape softens its edge rather
than leaving a hard cutout. Turn that off for any kernel whose weights
do not sum to one: a Laplacian over a uniformly opaque image sums to
zero, and would make the whole result invisible.
Parameters
kernel(list)options(?dict) —divisor(default 0),offset(default 0),edge(defaultEDGE_CLAMP),keep_alpha(default false).
Returns — self
Image.blur()
imagine.Image.blur(radius)
Blurs the image with a true Gaussian.
The radius is the blur’s standard deviation in pixels: about two thirds of each pixel’s contribution falls within that distance, and the visible spread is roughly three times it. Cost grows with the radius but only linearly, because the blur is separable.
Alpha is premultiplied for the duration, so blurring a shape on a transparent background does not drag a dark halo into its edge.
Parameters
radius(?number) — Greater than zero - Default: 2.
Returns — self
Image.sharpen()
imagine.Image.sharpen(strength)
Sharpens the image.
Parameters
strength(?number) — 1 is moderate; much above 3 starts producing halos - Default: 1.
Returns — self
Image.smooth()
imagine.Image.smooth(weight)
Softens the image with a weighted 3x3 average.
Cheaper and harsher than blur(), and fixed at one pixel of reach.
Parameters
weight(?number) — How much of the original to keep - Default: 8.
Returns — self
Image.emboss()
imagine.Image.emboss()
Turns the image into a grey relief, as if stamped into metal.
Returns — self
Image.edges()
imagine.Image.edges()
Leaves only the image’s edges, everything flat going black.
Returns — self
Image.mean_removal()
imagine.Image.mean_removal()
Exaggerates local detail by removing the local mean.
Returns — self
Image.pixelate()
imagine.Image.pixelate(size)
Replaces each block of pixels with its average, producing the familiar censoring mosaic.
Parameters
size(?number) — The block’s side in pixels - Default: 8.
Returns — self
Image.draw_image()
imagine.Image.draw_image(source: instance, x, y, options)
Draws another image onto this one.
The source is clipped to this image’s edges, and its position may be negative, so a sprite hanging off the top-left corner draws correctly.
var badge = Image.open('badge.png')
photo.draw_image(badge, 12, 12, { opacity: 0.8 })
Parameters
source(Image)x(?number) — Default: 0.y(?number) — Default: 0.options(?dict) —opacity(0-1, default 1),blend(defaultBLEND_NORMAL).
Returns — self
Image.place()
imagine.Image.place(source: instance, anchor, options)
Draws another image onto this one, positioned by anchor rather than by coordinates.
photo.place(watermark, BOTTOM_RIGHT, { margin: 16, opacity: 0.5 })
Parameters
source(Image)anchor(?string) — Default:CENTER.options(?dict) —margin(inset from the edges, default 0), plus everythingdraw_image()takes.
Returns — self
Image.mask()
imagine.Image.mask(mask: instance)
Uses another image as an alpha mask.
Each of this image’s pixels keeps its colour and takes its transparency from the mask: where the mask is opaque white this image shows through fully, where the mask is black or transparent this image disappears, and greys give partial transparency.
The mask’s own alpha counts too, so a shape drawn on a transparent background works as a mask without being filled in first.
The mask must be the same size as this image.
Parameters
mask(Image)
Returns — self
Raises BoundsError When the mask is a different size.
Image.flatten()
imagine.Image.flatten(background)
Composites the image over a solid colour, leaving it fully opaque.
This is what happens on export to a format without an alpha channel; doing it explicitly first lets you choose the colour and see the result.
Parameters
background(?Color|string|number) — Default: white.
Returns — self
Image.histogram()
imagine.Image.histogram() -> dict
Counts how many pixels hold each value, per channel.
Returns a dictionary of four 256-entry lists: red, green, blue and
luma, where luma is perceived brightness. Fully transparent pixels are
skipped, since their colour is not visible and would otherwise pile up
at whatever the buffer happens to hold there.
A histogram is what tells you an image is underexposed (everything bunched at the low end), flat (bunched in the middle), or clipped (a spike at 0 or 255).
Returns dict
Image.auto_levels()
imagine.Image.auto_levels(options)
Stretches the image’s tones to fill the full range.
The black and white points are found from the brightness histogram,
ignoring a small fraction at each end so that a handful of stray pixels
cannot decide the result. This is the automatic version of levels(),
and it is the first thing to try on a flat or hazy photograph.
An image that already spans the full range, or one with no visible pixels at all, is left alone.
Parameters
options(?dict) —clip(the fraction to ignore at each end, 0 to 0.2 - Default: 0.005),gamma(a midtone curve to apply as well - Default: 1).
Returns — self
Image.average_color()
imagine.Image.average_color() -> Color
The average colour of the image.
Pixels are weighted by their alpha, so a mostly transparent image reports the colour of the part you can actually see rather than having it washed out by whatever is behind the transparency. The returned colour’s own alpha is the mean alpha.
An image with nothing visible in it returns transparent black.
Returns Color
Image.dominant_colors()
imagine.Image.dominant_colors(count, options) -> list
The colours that occupy the most of the image, most common first.
The image is shrunk and reduced to a small palette first, so this costs about the same whatever the original size. Nearly transparent pixels are ignored.
The usual use is picking a background or accent colour to show while a photograph is still loading.
var accent = photo.dominant_colors(1)[0]
Parameters
count(?number) — How many to return - Default: 5.options(?dict) —sample(the size the image is reduced to before counting - Default: 96),palette(how many colours to quantize to - Default: 32).
Returns list
Image.difference()
imagine.Image.difference(other: instance) -> number
How different two images are, from 0 (identical) to 1.
The score is the mean difference across the colour channels, weighted by how opaque each pixel is in either image, so transparent regions do not count as agreement. Images of different sizes are never comparable and return 1.
if rendered.difference(expected) > 0.01 {
raise Exception('the rendering changed')
}
Parameters
other(Image)
Returns number
Image.text()
imagine.Image.text(x, y, text, font, color, options)
Draws a string.
x and y are the top-left corner of the text’s box, not its baseline,
because that is what you know when placing text in a layout. Pass { baseline: true }
to treat y as the first line’s baseline instead.
A \n starts a new line. Multi-line text is aligned by the align
option, which positions the lines against each other, not against the
image.
var font = Font.load('Inter.ttf').size(28)
card.text(24, 24, 'Hello\nthere', font, '#111111', {
align: ALIGN_CENTER,
line_height: 1.4,
})
Parameters
x(number)y(number)text(string)font(Font)color(Color|string|number)options(?dict) —align,line_height(multiplier, default 1),tracking(extra pixels between characters, default 0),baseline(bool, default false),width(wrap to this many pixels).
Returns — self
Image.text_size()
imagine.Image.text_size(text, font, options) -> dict
Measures a string as text() would draw it, without drawing it.
Returns a dictionary holding width, height, baseline and lines.
Parameters
text(string)font(Font)options(?dict) — The same optionstext()takes,widthincluded, so a measurement of wrapped text matches what would actually be drawn.
Returns dict
Image.place_text()
imagine.Image.place_text(text, font, color, anchor, options)
Draws a string positioned by anchor rather than by coordinates.
Parameters
text(string)font(Font)color(Color|string|number)anchor(?string) — Default:CENTER.options(?dict) —margin, plus everythingtext()takes.
Returns — self
Image.encode()
imagine.Image.encode(format, options) -> bytes
Encodes the image and returns the bytes.
Options understood, by format:
quality(1-100) for JPEG and AVIF. Defaults to 85 for JPEG and 80 for AVIF. It does not apply to WebP, which is written losslessly.compressionfor PNG:'fast','default'or'best'. All three are lossless; they trade encoding time for file size.speedfor AVIF (1-10, lower is slower and smaller) and for GIF (1-30, lower is slower and picks better colours; 15 by default).backgroundfor JPEG, the colour transparent pixels are flattened against. Defaults to white.threshold(0-255) for WBMP, the brightness cut.
Parameters
format(?string) — Default: the format this image was decoded from, orPNG.options(?dict)
Returns bytes
Raises EncodeError When the format cannot be written.
Image.save()
imagine.Image.save(path: string, options)
Writes the image to a file.
The format is taken from the path’s extension unless format overrides
it, so save('out.webp') writes a WebP.
Parameters
path(string)options(?dict) —format, plus everythingencode()takes.
Returns — self
Raises FormatError When the extension names no format this module
knows and no format option is given.
Image.to_data_url()
imagine.Image.to_data_url(format, options) -> string
Encodes the image as a data: URL, ready to drop into an img tag or a
stylesheet.
Base64 costs a third more bytes than the raw image, so this suits icons and small graphics rather than photographs.
Parameters
format(?string) — Default:PNG.options(?dict) — Everythingencode()takes.
Returns string
Image.to_png()
imagine.Image.to_png(options) -> bytes
Encodes the image as a PNG. Lossless, with alpha.
Parameters
options(?dict) —compression.
Returns bytes
Image.to_jpeg()
imagine.Image.to_jpeg(quality, options) -> bytes
Encodes the image as a JPEG. Lossy, no alpha.
Parameters
quality(?number) — 1-100 - Default: 85.options(?dict) —background.
Returns bytes
Image.to_webp()
imagine.Image.to_webp(options) -> bytes
Encodes the image as a WebP.
Parameters
options(?dict)
Returns bytes
Image.to_avif()
imagine.Image.to_avif(quality, options) -> bytes
Encodes the image as an AVIF.
Small files, slow encoding. Lower speed values are slower and produce
smaller files.
Parameters
quality(?number) — 1-100 - Default: 80.options(?dict) —speed(1-10, default 6).
Returns bytes
Image.to_gif()
imagine.Image.to_gif(options) -> bytes
Encodes the image as a single-frame GIF, quantized to 256 colours.
Parameters
options(?dict)
Returns bytes
Image.to_bmp()
imagine.Image.to_bmp(options) -> bytes
Encodes the image as a BMP.
Parameters
options(?dict)
Returns bytes
Image.to_tiff()
imagine.Image.to_tiff(options) -> bytes
Encodes the image as a TIFF.
Parameters
options(?dict)
Returns bytes
Image.to_qoi()
imagine.Image.to_qoi(options) -> bytes
Encodes the image as a QOI. Lossless with alpha, and several times faster than PNG to read and write.
Parameters
options(?dict)
Returns bytes
Image.to_tga()
imagine.Image.to_tga(options) -> bytes
Encodes the image as a Targa.
Parameters
options(?dict)
Returns bytes
Image.to_ico()
imagine.Image.to_ico(options) -> bytes
Encodes the image as a Windows icon.
Parameters
options(?dict)
Returns bytes
Image.to_wbmp()
imagine.Image.to_wbmp(threshold) -> bytes
Encodes the image as a one-bit Wireless Bitmap.
Parameters
threshold(?number) — The brightness cut, 0-255 - Default: 128.
Returns bytes
Image.to_string()
imagine.Image.to_string()
2026, Richard Ore and Zuri contributors