- A python package for accessing the internal variables of the JPEG file format such as DCT coefficients and quantization tables.
- See also jpeglib, which supports a comprehensive set of JPEG libraries.
Pick the easiest method that works for you, in order of convenience.
1. From PyPI:
pip install pyjpegio
Note
The distribution name on PyPI is pyjpegio, but the import name is still
jpegio. Install with pip install pyjpegio, then use import jpegio in
your code.
2. From GitHub:
pip install "git+https://github.com/dwgoon/jpegio.git"
3. From a local source checkout:
pip install .
Prebuilt wheels for Linux, macOS and Windows (CPython 3.9 through 3.13) are produced in CI with cibuildwheel, so method 1 needs no compiler. Methods 2 and 3 build the bundled libjpeg-turbo from source and require:
- A C/C++ compiler (MSVC on Windows, GCC on Linux, Clang on macOS).
CMakeandNumPy, installed automatically as build dependencies.NASMis optional; when present, libjpeg-turbo SIMD acceleration is enabled.Cythonis not needed for the default (C-API) build; it is only required for the optionalJPEGIO_BACKEND=cythonbuild.
pip install build
python -m build
The resulting wheel and source distribution are placed in the dist directory.
Cross-platform wheels are built in CI with
cibuildwheel.
This branch ships two interchangeable bindings to the same C++ backend,
selected at build time with the JPEGIO_BACKEND environment variable:
capi(default): a hand-written CPython C-API extension. No Cython is required to build it.cython: the Cython (.pyx) implementation. RequiresCythonin the build environment (it is intentionally not a default build dependency).
# default (C-API):
pip install .
# Cython backend (needs Cython in the build env):
pip install cython
JPEGIO_BACKEND=cython pip install . --no-build-isolation
Both backends expose the exact same Python API and produce identical results.
At runtime this package only requires:
At build time it additionally uses Cython, CMake and (optionally) NASM.
libjpeg-turbo is bundled and statically linked, so there is no external libjpeg
runtime dependency.
import jpegio as jio
jpeg = jio.read("image.jpg")
coef_array = jpeg.coef_arrays[0]
quant_tbl = jpeg.quant_tables[0]
# Modifying jpeg.coef_arrays...
# Modifying jpeg.quant_tables...
jio.write(jpeg, "image_modified.jpg")coef_arraysis a list ofnumpy.ndarrayobjects that represent the DCT coefficients of the YCbCr channels in the JPEG.quant_tablesis a list ofnumpy.ndarrayobjects that represent the quantization tables in the JPEG.
The pixel-domain (spatial) image is not decoded by default. Pass
read_spatial=True to also populate spatial_arrays:
jpeg = jio.read("image.jpg", read_spatial=True)
red_channel = jpeg.spatial_arrays[0]You can also utilize other variables (one of the simplest ways to find them is
to use dir(jpeg)). The names of the member variables follow the convention of
libjpeg.
jpegio exposes the JPEG internals that matter for JPEG steganography and steganalysis, with read/write access to the embedding-relevant attributes.
- All markers are preserved (not just COM).
jpeg.markersis a list of{"type": int, "data": bytes}for APP0..APP15 and COM, so EXIF/JFIF/ICC/Adobe round-trip and you can hide/read data in markers. - Read/write JPEG properties:
restart_interval,arith_code,optimize_coding,progressive_mode, color-space and dimension fields; plus read-onlydata_precision, JFIF density, Adobe transform.comp_infoedits are honoured on write. - The
jpegio.toolsmodule:
import jpegio as jio
from jpegio import tools
jpeg = jio.read("image.jpg")
z = tools.coefficients_zigzag(jpeg.coef_arrays[0]) # (H, W, 64) zigzag blocks
vals, cnts = tools.dct_histogram(jpeg.coef_arrays[0], mode=1) # per-mode histogram
capacity = tools.embedding_capacity(jpeg) # nzAC capacity
tools.set_coefficient(jpeg, 0, 1, 2, 3, 4, 7) # component, block row/col, (u, v), value
jpeg.markers.append({"type": jio.MARKER_COM, "data": b"payload"})
jio.write(jpeg, "stego.jpg")- The core parts of this package, implemented in C/C++, are adopted from the source code of Jessica Fridrich's laboratory.
- The functionality of libjpeg is provided by libjpeg-turbo, which is in turn based on the work of the IJG.
This package bundles and statically links libjpeg-turbo, which is redistributed under its own permissive (BSD-style) licenses. See NOTICE and third_party/libjpeg-turbo/LICENSE.md for details.
This software is based in part on the work of the Independent JPEG Group.