Skip to content

ImageOps

from blanket import ImageOps provides all 18 functions in Pillow's ImageOps submodule:

  • Tone and color: autocontrast, colorize, equalize, grayscale, invert, posterize, solarize.
  • Geometry: contain, cover, crop, deform, expand, fit, flip, mirror, pad, scale.
  • Orientation: exif_transpose, including in_place=True.
from blanket import Image, ImageOps

with Image.open("input.jpg") as image:
    upright = ImageOps.exif_transpose(image)
    thumbnail = ImageOps.fit(upright, (256, 256), method=Image.Resampling.LANCZOS)
    ImageOps.autocontrast(thumbnail).save("thumbnail.png")

Pixel processing runs in Rust, without a Pillow runtime dependency. Geometry supports all three Blanket modes; histogram and lookup operations accept L and RGB, while colorize requires L. grayscale accepts all three modes. The signatures, defaults, border forms, masks, CSS color arguments, and SupportsGetMesh protocol follow Pillow. Resizing supports all six Image.Resampling filters; mesh deformation supports nearest, bilinear, and bicubic sampling. Filtered RGBA operations use premultiplied alpha.

Note that ImageOps.crop(image, border=2) removes pixels from each side by a border width—its argument is not a rectangle. Use image.crop() for rectangle-based cropping.

Reference

autocontrast

autocontrast(image: Image, cutoff: float | tuple[float, float] = 0, ignore: int | Sequence[int] | None = None, mask: Image | None = None, preserve_tone: bool = False) -> Image

Stretch histogram endpoints with optional masks, ignored values and tails.

cutoff is a percentage, or separate (low, high) percentages. preserve_tone uses one luminance histogram for all color channels.

Parameters:

Name Type Description Default
image Image

Input image.

required
cutoff float | tuple[float, float]

Percentage discarded from histogram tails, or separate (low, high) percentages.

0
ignore int | Sequence[int] | None

Pixel value or sequence of values excluded from the histogram.

None
mask Image | None

Optional mask selecting pixels. Histogram operations require an L mask; compositing also accepts RGBA alpha.

None
preserve_tone bool

Use a shared luminance histogram to preserve relative channel tone.

False

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.autocontrast(image, cutoff=1)

colorize

colorize(image: Image, black: Color, white: Color, mid: Color | None = None, blackpoint: int = 0, whitepoint: int = 255, midpoint: int = 127) -> Image

Map an L image to an RGB gradient with two or three color stops.

Parameters:

Name Type Description Default
image Image

Input image.

required
black Color

Color mapped to the black point.

required
white Color

Color mapped to the white point.

required
mid Color | None

Optional color at the midpoint for a three-color gradient.

None
blackpoint int

Input intensity mapped to black, in 0 through 255.

0
whitepoint int

Input intensity mapped to white, in 0 through 255.

255
midpoint int

Input intensity mapped to the middle color.

127

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.colorize(image.convert("L"), "navy", "white")

contain

contain(image: Image, size: tuple[int, int], method: int = BICUBIC) -> Image

Resize to fit inside size while preserving the aspect ratio.

Parameters:

Name Type Description Default
image Image

Input image.

required
size tuple[int, int]

Output (width, height) in pixels.

required
method int

Resampling filter from Image.Resampling.

BICUBIC

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.contain(image, (4, 6))

cover

cover(image: Image, size: tuple[int, int], method: int = BICUBIC) -> Image

Resize to cover size while preserving the aspect ratio.

Parameters:

Name Type Description Default
image Image

Input image.

required
size tuple[int, int]

Output (width, height) in pixels.

required
method int

Resampling filter from Image.Resampling.

BICUBIC

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.cover(image, (4, 6))

pad

pad(image: Image, size: tuple[int, int], method: int = BICUBIC, color: Color | None = None, centering: tuple[float, float] = (0.5, 0.5)) -> Image

Contain the image and pad it to size with the selected background.

Parameters:

Name Type Description Default
image Image

Input image.

required
size tuple[int, int]

Output (width, height) in pixels.

required
method int

Resampling filter from Image.Resampling.

BICUBIC
color Color | None

Fill value, channel tuple, or CSS color string.

None
centering tuple[float, float]

Horizontal and vertical alignment in 0 through 1; 0.5 centers each axis.

(0.5, 0.5)

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.pad(image, (12, 8), color="white")

crop

crop(image: Image, border: int = 0) -> Image

Remove border pixels from each side of the image.

Like Pillow, also accepts (horizontal, vertical) or (left, top, right, bottom) border tuples. Use image.crop(box) to select a rectangle instead.

Parameters:

Name Type Description Default
image Image

Input image.

required
border int

Border width in pixels.

0

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.crop(image, border=1)

scale

scale(image: Image, factor: float, resample: int = BICUBIC) -> Image

Resize by a positive scale factor, rounding dimensions to pixels.

Parameters:

Name Type Description Default
image Image

Input image.

required
factor float

Positive multiplier for both image dimensions.

required
resample int

Resampling filter from Image.Resampling; supported filters depend on the operation.

BICUBIC

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.scale(image, 0.5)

deform

deform(image: Image, deformer: SupportsGetMesh, resample: int = BILINEAR) -> Image

Warp using a deformer mesh with nearest, bilinear or bicubic sampling.

Parameters:

Name Type Description Default
image Image

Input image.

required
deformer SupportsGetMesh

Object implementing getmesh(image) and returning destination boxes with source quadrilaterals.

required
resample int

Resampling filter from Image.Resampling; supported filters depend on the operation.

BILINEAR

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))


class IdentityMesh:
    def getmesh(self, image):
        width, height = image.size
        return [((0, 0, width, height), (0, 0, 0, height, width, height, width, 0))]


result = ImageOps.deform(image, IdentityMesh())

equalize

equalize(image: Image, mask: Image | None = None) -> Image

Equalize each channel using the histogram selected by an optional mask.

Parameters:

Name Type Description Default
image Image

Input image.

required
mask Image | None

Optional mask selecting pixels. Histogram operations require an L mask; compositing also accepts RGBA alpha.

None

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.equalize(image)

expand

expand(image: Image, border: Border = 0, fill: Color = 0) -> Image

Add a border filled with a pixel value or CSS color.

Parameters:

Name Type Description Default
image Image

Input image.

required
border Border

Integer, (horizontal, vertical), or (left, top, right, bottom) widths.

0
fill Color

Border value, channel tuple, or CSS color.

0

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.expand(image, border=2, fill="white")

fit

fit(image: Image, size: tuple[int, int], method: int = BICUBIC, bleed: float = 0.0, centering: tuple[float, float] = (0.5, 0.5)) -> Image

Crop to the requested aspect ratio and resize, with optional edge bleed.

Parameters:

Name Type Description Default
image Image

Input image.

required
size tuple[int, int]

Output (width, height) in pixels.

required
method int

Resampling filter from Image.Resampling.

BICUBIC
bleed float

Fraction to remove from each edge before fitting; must be less than 0.5.

0.0
centering tuple[float, float]

Horizontal and vertical alignment in 0 through 1; 0.5 centers each axis.

(0.5, 0.5)

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.fit(image, (4, 6))

flip

flip(image: Image) -> Image

Flip vertically.

Parameters:

Name Type Description Default
image Image

Input image.

required

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.flip(image)

grayscale

grayscale(image: Image) -> Image

Convert to 8-bit luminance.

Parameters:

Name Type Description Default
image Image

Input image.

required

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.grayscale(image)

invert

invert(image: Image) -> Image

Replace each channel value with 255 minus that value.

Parameters:

Name Type Description Default
image Image

Input image.

required

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.invert(image)

mirror

mirror(image: Image) -> Image

Flip horizontally.

Parameters:

Name Type Description Default
image Image

Input image.

required

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.mirror(image)

posterize

posterize(image: Image, bits: int) -> Image

Keep the highest bits of each channel (0 through 8).

Parameters:

Name Type Description Default
image Image

Input image.

required
bits int

Number of high bits to retain per channel, from 0 through 8.

required

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.posterize(image, bits=4)

solarize

solarize(image: Image, threshold: int = 128) -> Image

Invert channel values greater than or equal to threshold.

Parameters:

Name Type Description Default
image Image

Input image.

required
threshold int

Intensity threshold, on the 0 through 255 scale.

128

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.solarize(image, threshold=128)

exif_transpose

exif_transpose(image: Image, *, in_place: Literal[True]) -> None
exif_transpose(image: Image, *, in_place: Literal[False] = False) -> Image
exif_transpose(image: Image, *, in_place: bool = False) -> Image | None

Apply EXIF orientation and remove it from EXIF and XMP metadata.

Return a copy by default, or update the original and return None when in_place=True. Other EXIF entries and their offsets are preserved.

Parameters:

Name Type Description Default
image Image

Input image.

required
in_place bool

Modify the input and return None when true; otherwise return a transformed copy.

False

Examples:

from blanket import Image, ImageOps

image = Image.new("RGB", (8, 8), (40, 100, 180))
result = ImageOps.exif_transpose(image)

SupportsGetMesh

Bases: Protocol

A deformer returning destination boxes and source TL, BL, BR, TR quads.

getmesh

getmesh(image: Image) -> list[tuple[tuple[int, int, int, int], tuple[float, float, float, float, float, float, float, float]]]

Describe destination rectangles and their source quadrilaterals.

Parameters:

Name Type Description Default
image Image

Image being deformed, used to determine source dimensions.

required

Returns:

Type Description
list[tuple[tuple[int, int, int, int], tuple[float, float, float, float, float, float, float, float]]]

Pairs of destination (left, top, right, bottom) rectangles and source

list[tuple[tuple[int, int, int, int], tuple[float, float, float, float, float, float, float, float]]]

coordinates in top-left, bottom-left, bottom-right, top-right order.

Examples:

from blanket import Image, ImageOps


class IdentityMesh:
    def getmesh(self, image):
        width, height = image.size
        return [((0, 0, width, height), (0, 0, 0, height, width, height, width, 0))]


image = Image.new("RGB", (8, 8), "navy")
result = ImageOps.deform(image, IdentityMesh())