Image File Formats
Independent practical guide. Canonical source: official Image file formats documentation.
Pillow reads and writes the common web and photo formats (JPEG, PNG, WebP, GIF, TIFF, AVIF) plus a long tail of older and specialist ones. Read and write support differ: some formats are read-only (PSD, for example) and PDF is write-only. Run python -m PIL --report to see exactly what your installation supports. For measured file sizes and conversion recipes, see converting between image formats.
| Format | Read | Write | Notes |
|---|---|---|---|
| JPEG / JPG | ✅ | ✅ | Lossy. No alpha. Most common photo format. |
| PNG | ✅ | ✅ | Lossless with alpha. Best for UI / screenshots. |
| GIF | ✅ | ✅ | Animated. 256-colour palette only. |
| WebP | ✅ | ✅ | Lossy/lossless, animated. Best web compression. |
| TIFF / TIF | ✅ | ✅ | Multi-page, raw, high-quality. Used in print/medical. |
| BMP | ✅ | ✅ | Uncompressed raster. Windows bitmap. |
| ICO | ✅ | ✅ | Windows icon format with multiple sizes. |
| ❌ | ✅ | Can write images as PDF pages. Read not supported. | |
| EPS / PS | ✅ * | ✅ | Requires Ghostscript for reading. |
| SVG | ❌ | ❌ | Vector format; Pillow cannot read it. Rasterise to PNG first (e.g. with CairoSVG), then open the PNG. |
| HEIC / HEIF | ✅ * | ✅ * | Requires pillow-heif plugin package. |
| PPM / PBM / PGM | ✅ | ✅ | Portable bitmap formats (Unix legacy). |
| TGA | ✅ | ✅ | Targa format. Common in 3D/game pipelines. |
| PCX | ✅ | ✅ | ZSoft PC Paintbrush. |
| SGI / RGB | ✅ | ✅ | Silicon Graphics Image format. |
| DDS | ✅ | ✅ | DirectDraw Surface — used in DirectX games. |
| AVIF | ✅ | ✅ | Built into the official wheels since Pillow 11.3.0 (except Windows ARM64 and iOS). Older versions: pillow-avif-plugin. |
| XBM | ✅ | ✅ | X11 bitmap format. |
| SPIDER | ✅ | ✅ | SPIDER image format (data visualization). |
| IM | ✅ | ✅ | LabEye IM format. |
* = Requires optional dependency or plugin
JPEG
JPEG is the most common format for photographs. It uses lossy compression that significantly reduces file size but cannot store alpha transparency. The JPEG/JFIF format supports RGB, L, and CMYK modes.
OSError. Always convert("RGB") first.
PNG
PNG is a lossless format supporting transparency. It supports modes 1, L, P, RGB, and RGBA. PNG files contain a series of chunks — Pillow exposes most of these via the info dictionary.
PNG DPI metadata
To embed print resolution in a PNG, pass dpi=(x, y) to save(). Pillow writes it to the pHYs chunk; read it back with img.info.get("dpi").
GIF
GIF supports animation and transparency but is limited to 256 colours per frame. Pillow reads and writes GIF files, including animated ones.
WebP (support & save options)
WebP provides both lossy and lossless compression with support for transparency and animation. It generally achieves 25-35% smaller files than JPEG at the same visual quality, making it the recommended format for modern web images.
TIFF
TIFF is a flexible raster format widely used in print, medical imaging, and GIS industries. Pillow supports multi-page TIFF reading, writing, and a variety of compression options.
BMP
BMP is the native Windows bitmap format. It stores uncompressed image data and supports a wide range of pixel depths (1, 4, 8, 16, 24, 32 bit). Modes: 1, L, P, RGB. Writing is limited to these modes.
ICO (Windows Icon)
ICO files contain multiple image sizes in a single file. Pillow can read and write ICO files, embedding multiple sizes.
PDF (Write natively, Read via pdf2image)
Pillow natively exports single-page or multi-page PDF documents. To convert PDF documents into Pillow Images for processing, use the standard pdf2image wrapper around Poppler.
EPS / PS (PostScript)
Pillow can write EPS format and can read it if Ghostscript is installed. Ghostscript must be on the system path for rasterization of EPS to work.
SVG (Read-Only via Plugins)
Pillow's core does not support SVG. To render SVG files with Pillow, use a third-party library such as cairosvg, svglib, or Wand (ImageMagick binding) to first convert the SVG to PNG, then open it in Pillow.
HEIC / HEIF (via plugin)
HEIC is Apple's default photo format since iOS 11. Pillow supports it through the pillow-heif plugin.
Other Supported Formats
| Format | Extension | Notes |
|---|---|---|
| PPM / PBM / PGM / PNM | .ppm .pbm .pgm .pnm | Portable Any Map. Simple uncompressed formats. |
| TGA / TARGA | .tga .vda .icb .vst | Targa image. No magic number — extension-based detection. |
| PCX | .pcx | ZSoft PC Paintbrush. Modes: 1, L, P, RGB. |
| SGI | .sgi .rgb .bw | Silicon Graphics native format. |
| DDS | .dds | DirectDraw Surface. Used in DirectX/OpenGL games. |
| IM | .im | LabEye IM format. |
| XBM | .xbm | X11 bitmap. Mode: 1 only. |
| XPM | .xpm | X11 colour pixmap. Read only. |
| FITS | .fits .fit .fts | NASA Flexible Image Transport System. Scientific imagery. |
| JPEG 2000 | .jp2 .j2k .jpf .j2c | Wavelet compression JPEG successor. Modes: L, RGB, RGBA. |
| PSD | .psd | Adobe Photoshop. Read only, flattened. |
| DCX | .dcx | Intel FAX format (multipage PCX). |
| MSP | .msp | Windows 1.x/2.x Paint. Mode: 1 only. |
Tested: what each format really supports
The tables in this section are printed by Pillow 12.3.0 itself, so they reflect the installed version rather than a list typed by hand.
How many formats Pillow handles
from PIL import Image, features
Image.init() # load every format plugin
readable, writable = set(Image.OPEN), set(Image.SAVE)
print(len(readable), "formats can be opened,", len(writable), "can be saved")
print("save-only:", sorted(writable - readable))
print("open-only (sample):", sorted(readable - writable)[:12], "...")
print("HEIF/HEIC readable without a plugin:", "HEIF" in readable)
print("codecs:", {name: features.check(name) for name in ["jpg", "zlib", "webp", "avif", "jpg_2000", "libtiff"]})
43 formats can be opened, 30 can be saved
save-only: ['MPO', 'PALM', 'PDF']
open-only (sample): ['CUR', 'DCX', 'FITS', 'FLI', 'FTEX', 'GBR', 'IMT', 'IPTC', 'MCIDAS', 'MPEG', 'PCD', 'PIXAR'] ...
HEIF/HEIC readable without a plugin: False
codecs: {'jpg': True, 'zlib': True, 'webp': True, 'avif': True, 'jpg_2000': True, 'libtiff': True}
Pillow reads far more formats than it writes. PDF is save-only (use pdf2image or PyMuPDF to read PDFs).
HEIC/HEIF is missing from both lists: it needs the pillow-heif plugin.
Size, transparency, animation and bit depth per format
import io
from PIL import Image
photo = Image.open("photo.jpg").resize((800, 534))
logo = Image.open("logo.png") # RGBA with transparent corners
frames = [photo, photo.transpose(Image.Transpose.FLIP_LEFT_RIGHT)]
def save(img, fmt, **kw):
buf = io.BytesIO()
img.save(buf, fmt, **kw)
buf.seek(0)
return buf
def check(fn):
try:
return fn()
except Exception:
return "-"
print(f"{'format':<9}{'photo KB':>9} {'keeps alpha':<12}{'animation':<10}{'16-bit grey'}")
grey16 = photo.convert("I").point(lambda v: v * 257).convert("I;16")
for fmt in ["JPEG", "PNG", "WEBP", "AVIF", "GIF", "TIFF", "BMP", "JPEG2000", "TGA", "PPM"]:
kb = check(lambda: f"{save(photo, fmt).getbuffer().nbytes / 1024:.0f}")
alpha = check(lambda: "yes" if Image.open(save(logo, fmt)).convert("RGBA").getpixel((2, 2))[3] == 0 else "no")
anim = check(lambda: "yes" if getattr(Image.open(save(frames[0], fmt, save_all=True, append_images=frames[1:])),
"n_frames", 1) > 1 else "no")
deep = check(lambda: "yes" if Image.open(save(grey16, fmt)).mode in ("I;16", "I", "I;16B") else "no")
print(f"{fmt:<9}{kb:>9} {alpha:<12}{anim:<10}{deep}")
format photo KB keeps alpha animation 16-bit grey
JPEG 39 - - -
PNG 426 yes yes yes
WEBP 28 yes yes no
AVIF 34 yes yes no
GIF 152 yes yes no
TIFF 1252 yes yes yes
BMP 1252 no - -
JPEG2000 411 yes - yes
TGA 1252 yes - -
PPM 1252 no - yes
"-" means saving raised an error; "no" means the file saved, but the feature was lost when it was opened again. The photo sizes use each format's default settings, so they compare defaults rather than best-case compression; see reducing file size and converting formats for tuned settings. GIF keeps transparency as a single palette entry, so soft edges become hard, and it has at most 256 colours per frame. PNG's "yes" for animation is APNG, which browsers play but many image viewers show as a still. BMP writes 32-bit pixels including the alpha byte, but with a header that does not declare an alpha channel, so readers (Pillow included) open it as plain RGB: hence "no".