OpenCV
| Language | Python 3 (bindings of the C++ library) |
|---|---|
| License | Apache 2.0 |
| Repository | github.com/opencv/opencv, Python packages: opencv-python |
| Documentation | docs.opencv.org, imread |
| Depends on | NumPy (the BMP codec is built into OpenCV) |
| Read / write | yes, 1-32 bit, RLE4, RLE8, bit fields / yes, 8-bit gray, 24-bit, 32-bit with alpha |
OpenCV is a computer vision library. cv2.imread returns an image as a NumPy array and cv2.imwrite saves one; both choose the format from the file extension. The BMP codec is OpenCV’s own code, so BMP works even in minimal builds without libpng or libjpeg.
It reads palette, 16, 24 and 32-bit BMP files including RLE compression. It writes 8-bit grayscale (with a gray palette), 24-bit BGR and 32-bit BGRA files. Since OpenCV 4.13, 4-channel images are written with a V5 header and alpha mask; pass cv2.IMWRITE_BMP_COMPRESSION_RGB for the older 40-byte header. Channels are in BGR order, and imread drops alpha unless you pass cv2.IMREAD_UNCHANGED.
Installation#
Shell
pip install opencv-python
# on servers without a GUI:
pip install opencv-python-headless
Basic usage: read and write a BMP#
Python
import cv2
img = cv2.imread("in.bmp", cv2.IMREAD_UNCHANGED)
if img is None:
raise SystemExit("cannot read in.bmp")
print(img.shape, img.dtype) # e.g. (480, 640, 3) uint8 -> height, width, BGR
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if img.ndim == 3 else img
if not cv2.imwrite("gray.bmp", gray): # 8-bit BMP with a gray palette
raise SystemExit("cannot write gray.bmp")
How to write a 32-bit BMP with alpha#
Python
import cv2
bgra = cv2.imread("in.png", cv2.IMREAD_UNCHANGED) # 4 channels if the PNG has alpha
cv2.imwrite("alpha.bmp", bgra) # V5 header with alpha mask (OpenCV 4.13+)
# 40-byte header, for old programs (they usually ignore the alpha byte)
cv2.imwrite("alpha-legacy.bmp", bgra,
[cv2.IMWRITE_BMP_COMPRESSION, cv2.IMWRITE_BMP_COMPRESSION_RGB])
How to convert BMP to PNG#
Python
import cv2
img = cv2.imread("in.bmp", cv2.IMREAD_UNCHANGED)
cv2.imwrite("out.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 9])
How to encode and decode a BMP in memory#
Python
import cv2
import numpy as np
ok, buf = cv2.imencode(".bmp", img) # 1-D uint8 array with the BMP file
bmp_bytes = buf.tobytes()
decoded = cv2.imdecode(np.frombuffer(bmp_bytes, np.uint8), cv2.IMREAD_UNCHANGED)
How to get BMP width and height#
OpenCV has no header-only reader; read the 2 fields from the BMP header with struct:
Python
import struct
with open("in.bmp", "rb") as f:
header = f.read(26)
if header[:2] != b"BM":
raise ValueError("not a BMP file")
width, height = struct.unpack("<ii", header[18:26])
print(width, abs(height)) # negative height means top-down rows
Tips#
- Convert to RGB with
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)before passing the array to Pillow, Matplotlib or a model that expects RGB. cv2.imreadcan fail on non-ASCII paths on Windows. Usecv2.imdecode(np.fromfile(path, np.uint8), cv2.IMREAD_UNCHANGED)instead.