Documentation Menu

Concepts

Independent practical guide. Canonical source: official Concepts documentation.

Pillow works with raster images: a grid of pixels with a fixed width and height. Vector formats such as SVG have to be rasterised by another library before Pillow can use them.

Bands

Each image is made of one or more bands (channels). A greyscale image has a single band; a colour photo has three ('R', 'G', 'B'); a transparent PNG usually has four, the fourth being alpha ('A'). All bands of an image share the same size and bit depth. img.getbands() lists them, img.split() returns one single-band image per band, and Image.merge() puts them back together.

Working with Bands
from PIL import Image im = Image.open("logo.png") # an RGBA image print(im.getbands()) # ('R', 'G', 'B', 'A') # Split into individual band images r, g, b, a = im.split() # Merge bands back (maybe with a modified alpha) out = Image.merge("RGBA", (r, g, b, a))

Modes

The mode is a short string that says how each pixel is stored: how many bands, and how many bits per band. It decides which operations are allowed; for example, JPEG cannot store RGBA, and many filters do not accept palette (P) images. Check it with img.mode and change it with img.convert().

ModeDescriptionBands
1Pure black and white: each pixel is on or off (Pillow still uses one byte per pixel in memory).1
L8-bit pixels, grayscale (Luminance).1
P8-bit index into a palette of up to 256 colours (GIFs and small PNGs).1
RGB3×8-bit pixels, true colour.3
RGBA4×8-bit pixels, true colour with transparency mask.4
CMYK4×8-bit pixels, colour separation. Used in print workflows.4
YCbCr3×8-bit pixels, colour video format (JPEG standard).3
LAB3×8-bit pixels, the L*a*b color space.3
HSV3×8-bit pixels, Hue (0-255 scaled 0-360°), Saturation, Value.3
I32-bit signed integer pixels.1
F32-bit floating point pixels.1
LAL with alpha.2
PAP with alpha.2
RGBaRGB with pre-multiplied alpha.4
LaL with pre-multiplied alpha.2
I;1616-bit unsigned integer pixels.1
I;16B16-bit big-endian unsigned integer pixels.1
Mode Conversion & Alpha Transparency
# Check current mode print(im.mode) # 'RGB' # Convert to grayscale gray = im.convert("L") # Add Alpha Transparency Channel (RGB → RGBA) rgba = im.convert("RGBA") rgba.putalpha(128) # 50% opacity across entire image # RGB → CMYK (for commercial print) cmyk = im.convert("CMYK")

Coordinate System (origin at upper-left)

Pillow uses a Cartesian coordinate system with the origin (0,0) in the upper left corner. Note that coordinates refer to pixel corners, not pixel centers. So the bounding box for a 100×100 pixel image is: (0, 0, 100, 100).

ConceptValue
OriginTop-left corner (0, 0)
X-axisIncreases rightward (width)
Y-axisIncreases downward (height)
Bounding box(left, upper, right, lower) — exclusive on right and lower

Palette Mode

Palette (P mode) images use a colour lookup table. Each pixel value is an index into this table. This is used by GIF, which is limited to 256 unique colours per frame.

Palette Operations
# Convert to palette mode — quantize to 256 colors p_img = im.convert("P") # Quantize with explicit number of colors p_img = im.quantize(colors=128) # Get the raw palette data palette = p_img.getpalette() # flat list: [R,G,B, R,G,B, ...] # Save as GIF p_img.save("output.gif")

The Info Attribute

The im.info dictionary is populated by the file decoder with format-specific metadata. Common entries include DPI, comments, and EXIF data. This dictionary is not automatically written on save() — you must explicitly pass parameters to the save method.

Reading Image Metadata
from PIL import Image im = Image.open("photo.jpg") # Access info dict print(im.info) # {'jfif': 257, 'jfif_version': (1, 1), 'dpi': (72, 72), ...} # EXIF via getexif() from PIL import ExifTags exif = im.getexif() for tag_id, val in exif.items(): print(ExifTags.TAGS.get(tag_id, tag_id), val)

Filters

The ImageFilter module defines a set of predefined image filters and a generic kernel filter. Filters are applied using im.filter().

FilterCategoryDescription
BLURBlurBox blur.
GaussianBlur(radius)BlurGaussian bell-curve blur. Default radius=2.
BoxBlur(radius)BlurEach output pixel is the average of the square neighbourhood.
CONTOUREdgeFind image contours.
DETAILSharpenEnhance detail.
EDGE_ENHANCEEdgeEdge enhancement filter.
EDGE_ENHANCE_MOREEdgeMore aggressive edge enhancement.
EMBOSSEffectEmboss image.
FIND_EDGESEdgeFind sharp edges.
SHARPENSharpenSharpen image.
SMOOTHSmoothSmooth image.
SMOOTH_MORESmoothMore aggressive smoothing.
UnsharpMask(radius, percent, threshold)SharpenUnsharp mask. radius=2, percent=150, threshold=3.
Kernel(size, kernel)CustomCreate custom convolution kernel.
RankFilter(size, rank)RankPicks rank-th minimum pixel in each neighbourhood.
MedianFilter(size)RankPicks median pixel — good for "salt and pepper" noise.
MinFilter(size)RankPicks minimum (darkest) pixel in neighbourhood.
MaxFilter(size)RankPicks maximum (brightest) pixel in neighbourhood.