Mode mismatches cause most save errors and odd colours, for example saving RGBA as JPEG or reading palette PNGs.
An image's mode defines its bands (channels) and bit depth. The common ones:
"RGB": 3 x 8-bit;"RGBA": plus an alpha (transparency) band"L": 8-bit grayscale (luminance);"LA": grayscale plus alpha"1": 1-bit black and white, stored one byte per pixel"P": palette mode: each pixel is an index into a colour table of up to 256 entries (GIFs, many PNGs)"CMYK": printing; many JPEGs from print workflows use it"I;16","I","F": 16-bit and 32-bit integer and float images, used for scientific and depth data
im.convert(mode) returns a converted copy. RGB to L uses the weights L = R*299/1000 + G*587/1000 + B*114/1000. getbands() lists the bands and split() returns one L image per band.
Typical fixes you'll need:
- Before saving as JPEG, convert
RGBAorPtoRGB, because JPEG has no alpha or palette and Pillow raisesOSError: cannot write mode RGBA as JPEG. - After
Image.openon a PNG or GIF, check for"P"mode before doing pixel maths: values are palette indices, not colours.convert("RGB")orconvert("RGBA")resolves them. - Dropping alpha with
convert("RGB")discards transparency, so transparent pixels show whatever colour they stored, often black. Composite onto a background first if appearance matters.
convert("1") dithers by default (Floyd-Steinberg); pass dither=Image.Dither.NONE for a plain threshold.
Example
from PIL import Image
rgba = Image.new("RGBA", (4, 4), (255, 0, 0, 128)) # half-transparent red
print(rgba.mode, rgba.getbands()) # RGBA ('R', 'G', 'B', 'A')
try:
rgba.save("out.jpg")
except OSError as e:
print("error:", e) # cannot write mode RGBA as JPEG
rgba.convert("RGB").save("out.jpg") # works
gray = Image.new("RGB", (1, 1), (255, 0, 0)).convert("L")
print(gray.getpixel((0, 0))) # 76
pal = Image.new("RGB", (2, 1), (0, 128, 255)).convert("P")
print(pal.mode, pal.getpixel((0, 0))) # P <an index, not a colour>
print(pal.convert("RGB").getpixel((0, 0))) # (0, 153, 255) nearest palette colour
r, g, b, a = rgba.split()
print(a.mode, a.getpixel((0, 0))) # L 128Remember
- Mode = bands + bit depth: RGB, RGBA, L, 1, P, CMYK, I;16, F
convert(mode)returns a converted copy- Convert RGBA/P to RGB before saving JPEG
- P-mode pixels are palette indices, not colours
Watch out for
- Doing arithmetic on a P-mode image's pixel values as if they were colours or intensities.