PyTurboJPEG: High-performance JPEG Handling
PyTurboJPEG is a Python wrapper for the high-performance libjpeg-turbo library, enabling fast decoding and encoding of JPEG images. It leverages the underlying C library for significant speed improvements over pure Python or slower image processing libraries. The library is actively maintained with regular releases, often reflecting updates and features from the upstream libjpeg-turbo project. Current version is 2.2.0.
Common errors
-
OSError: cannot open shared object file: libturbojpeg.so.0: No such file or directory
cause The `libjpeg-turbo` shared library is not installed or not found in standard system library paths.fixInstall `libjpeg-turbo` using your system's package manager (e.g., `sudo apt-get install libturbojpeg0` on Linux, `brew install libjpeg-turbo` on macOS) or download and place the library file (e.g., `libturbojpeg.so.0`) in a directory listed in your system's dynamic linker search paths (`LD_LIBRARY_PATH`, `DYLD_LIBRARY_PATH`, `PATH`). Alternatively, initialize `TurboJPEG` with the explicit path: `jpeg = TurboJPEG('/usr/local/lib/libturbojpeg.so.0')`. -
TypeError: encode() got an unexpected keyword argument 'old_param'
cause You are using an argument name or a parameter that was removed or renamed in a newer version of PyTurboJPEG (most likely after v2.0.0 API migration).fixCheck the official PyTurboJPEG GitHub README or source code for the correct `encode()`/`decode()` method signatures for your installed version. Adjust your keyword arguments accordingly. -
ValueError: Input array is not C-contiguous
cause The input NumPy array's byte representation (obtained via `.tobytes()`) is not C-contiguous, which is required by `libjpeg-turbo` for direct memory access.fixBefore passing a NumPy array's bytes to `encode()` or `decode()`, ensure it is C-contiguous by calling `.copy(order='C')` on the array: `jpeg.encode(my_array.copy(order='C').tobytes(), ...)`.
Warnings
- breaking Version 2.0.0 migrated to the TurboJPEG 3.1.x function-based API. While the Python `TurboJPEG` class structure remains similar, underlying C API changes might lead to `TypeError` or `ValueError` if specific (especially low-level or less common) parameters or flag combinations from pre-2.0.0 versions are used.
- gotcha PyTurboJPEG is a wrapper library and requires the native `libjpeg-turbo` shared library (e.g., `libturbojpeg.so.0` on Linux, `libturbojpeg.dylib` on macOS, `turbojpeg.dll` on Windows) to be installed on your system. Without it, PyTurboJPEG cannot function and will raise an `OSError`.
- gotcha PyTurboJPEG's performance benefits are maximized with `numpy` arrays, but it expects input buffers (e.g., from `numpy.ndarray.tobytes()`) to be C-contiguous. If you pass a non-contiguous array, it may result in incorrect output or errors.
- gotcha Versions 2.1.0 and newer introduce support for 12-bit and 16-bit precision JPEGs, as well as lossless JPEG. If your application previously only handled 8-bit standard JPEGs, ensure your decoding and encoding pipelines explicitly manage precision settings if you encounter these new formats, to avoid unexpected truncation or errors.
Install
-
pip install pyturbojpeg
Imports
- TurboJPEG
from pyturbojpeg import TurboJPEG
Quickstart
from pyturbojpeg import TurboJPEG, TJPF_BGR, TJ_BGR
import numpy as np
import os
# Instantiate TurboJPEG. Optionally, pass the path to libturbojpeg.so.0, .dylib, or .dll
# Example: jpeg = TurboJPEG('/usr/local/lib/libturbojpeg.so.0')
jpeg = TurboJPEG()
# --- Encode Example ---
# Create a dummy BGR image (e.g., from OpenCV or Pillow in BGR mode)
width, height = 640, 480
# For simplicity, create a blank image; in real use, this would be actual image data
# PyTurboJPEG expects contiguous C-style arrays for input
dummy_img_array = np.zeros((height, width, 3), dtype=np.uint8)
# Set a pixel to demonstrate it's not entirely blank, just to ensure data is there
dummy_img_array[50, 50] = [255, 0, 0] # Blue pixel
# Encode the NumPy array (its byte representation) to JPEG
# TJPF_BGR indicates the input pixel format
try:
jpeg_data = jpeg.encode(dummy_img_array.tobytes(), width, height, TJPF_BGR, quality=85)
print(f"Successfully encoded JPEG data. Size: {len(jpeg_data)} bytes")
# Save to a file for verification (optional)
# with open('output.jpg', 'wb') as f:
# f.write(jpeg_data)
# --- Decode Example ---
# Decode the JPEG data back to raw pixel data
# TJ_BGR indicates the desired output colorspace (constant for BGR output)
decoded_image_data, decoded_width, decoded_height, decoded_pix_fmt, decoded_colorspace = \
jpeg.decode(jpeg_data, TJ_BGR)
print(f"Decoded image: {decoded_width}x{decoded_height}, "
f"Pixel Format: {decoded_pix_fmt}, Colorspace: {decoded_colorspace}")
# Convert decoded raw data back to a NumPy array
decoded_array = np.frombuffer(decoded_image_data, dtype=np.uint8).reshape((decoded_height, decoded_width, 3))
print(f"Decoded NumPy array shape: {decoded_array.shape}")
except Exception as e:
print(f"An error occurred: {e}")
print("Please ensure libjpeg-turbo is correctly installed and discoverable by PyTurboJPEG.")
print("You might need to set LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (macOS), or PATH (Windows).")
print("Alternatively, explicitly pass the library path to TurboJPEG() constructor.")