Skip to main content

Python wrapper for multithreaded .png image file optimizer oxipng

Project description

pyoxipng

CI PyPI

Python wrapper for multithreaded .png image file optimizer oxipng (written in Rust). Use pyoxipng to reduce the file size of your PNG images.

Jump to a section

Installation

Install from PyPI:

pip install pyoxipng

Import in your Python code:

import oxipng

API

oxipng.optimize(input, output=None, **kwargs)

Optimize a file on disk.

Parameters:

  • input (str | bytes | PathLike) – path to input file to optimize
  • output (str | bytes | PathLike, optional) – path to optimized output result file. If not specified, overwrites input. Defaults to None
  • **kwargsOptions

Returns

  • None

Raises

  • oxipng.PngError – optimization could not be completed

Examples:

Optimize a file on disk and overwrite

oxipng.optimize("/path/to/image.png")

Optimize a file and save to a new location:

oxipng.optimize("/path/to/image.png", "/path/to/image-optimized.png")

oxipng.optimize_from_memory(data, **kwargs)

Optimize raw data from a PNG file loaded in Python as a bytes object:

Parameters:

  • data (bytes) – raw PNG data to optimize
  • **kwargsOptions

Returns

  • (bytes) – optimized raw PNG data

Raises

  • oxipng.PngError – optimization could not be completed

Examples:

data = ...  # bytes of png data
optimized_data = oxipng.optimize_from_memory(data)
with open("/path/to/image-optimized.png", "wb") as f:
    f.write(optimized_data)

oxipng.RawImage

Create an optimized PNG file from raw image data:

raw = oxipng.RawImage(data, width, height)
optimized_data = raw.create_optimized_png()

By default, assumes the input data is 8-bit, row-major RGBA, where every 4 bytes represents one pixel with Red-Green-Blue-Alpha channels. To interpret non-RGBA data, specify a color_type parameter with the oxipng.ColorType class:

Method Description
oxipng.ColorType.grayscale(int | None) Grayscale, with one color channel. Specify optional shade of gray that should be rendered as transparent.
oxipng.ColorType.rgb(tuple[int, int, int]) RGB, with three color channels. Specify optional color value that should be rendered as transparent.
oxipng.ColorType.indexed(list[[tuple[int, int, int, int]]) Indexed, with one byte per pixel representing a color from the palette. Specify palette containing the colors used, up to 256 entries.
oxipng.ColorType.grayscale_alpha() Grayscale + Alpha, with two color channels.
oxipng.ColorType.rgba() RGBA, with four color channels.

Parameters:

  • data (bytes | bytearray) – Raw image data bytes. Format depends on color_type and bit_depth parameters
  • width (int) – Width of raw image, in pixels
  • height (int) – Height of raw image, in pixels
  • color_type ([oxipng.ColorType, optional) – Descriptor for color type used to represent this image. Optional, defaults to oxipng.ColorType.rgba()
  • bit_depth (int, optional) – Bit depth of raw image. Optional, defaults to 8

Examples:

Save RGB image data from a JPEG file, interpreting black pixels as transparent.

from PIL import Image
import numpy as np

# Load an image file with Pillow
jpg = Image.open("/path/to/image.jpg")

# Convert to RGB numpy array
rgb_array = np.array(jpg.convert("RGB"), dtype=np.uint8)
height, width, channels = rgb_array.shape

# Create raw image with sRGB color profile
data = rgb_array.tobytes()
color_type = oxipng.ColorType.rgb((0, 0, 0))  # black is transparent
raw = oxipng.RawImage(data, width, height, color_type=color_type)
raw.add_png_chunk(b"sRGB", b"\0")

# Optimize and save
optimized = raw.create_optimized_png(level=6)
with open("/path/to/image/optimized.png", "wb") as f:
    f.write(optimized)

Save with data where bytes reference a color palette

data = b"\0\1\2..."  # get index data
palette = [[0, 0, 0, 255], [1, 23, 234, 255], ...]
color_type = oxipng.ColorType.indexed(palette)
raw = oxipng.RawImage(data, 100, 100, color_type=color_type)
optimized = raw.create_optimized_png()

Methods:

add_png_chunk(name, data)

Add a png chunk, such as b"iTXt", to be included in the output

Parameters:

  • name (bytes) – PNG chunk identifier
  • data (bytes | bytarray)

Returns:

  • None

add_icc_profile(data)

Add an ICC profile for the image

Parameters:

  • data (bytes) – ICC profile data

Returns:

  • None

create_optimized_png(**kwargs)

Create an optimized png from the raw image data using the options provided

Parameters:

Returns:

  • (bytes) optimized PNG image data

Options

optimize , optimize_from_memory and RawImage.create_optimized_png accept the following options as keyword arguments.

Example:

oxipng.optimize("/path/to/image.png", level=6, fix_errors=True, interlace=oxipng.Interlacing.Adam7)
Option Description Type Default
level Set the optimization level to an integer between 0 and 6 (inclusive) int 2
fix_errors Attempt to fix errors when decoding the input file rather than throwing PngError bool False
force Write to output even if there was no improvement in compression bool False
filter Which filters to try on the file. Use Use enum values from oxipng.RowFilter set[RowFilter] {RowFilter.NoOp}
interlace Whether to change the interlacing type of the file. None will not change current interlacing type Interlacing | None None
optimize_alpha Whether to allow transparent pixels to be altered to improve compression bool False
bit_depth_reduction Whether to attempt bit depth reduction bool True
color_type_reduction Whether to attempt color type reduction bool True
palette_reduction Whether to attempt palette reduction bool True
grayscale_reduction Whether to attempt grayscale reduction bool True
idat_recoding If any type of reduction is performed, IDAT recoding will be performed regardless of this setting bool True
scale_16 Whether to forcibly reduce 16-bit to 8-bit by scaling bool False
strip Which headers to strip from the PNG file, if any. Specify with oxipng.StripChunks StripChunks StripChunks.none()
deflate Which DEFLATE algorithm to use. Specify with oxipng.Deflaters Deflaters Deflaters.libdeflater()
fast_evaluation Whether to use fast evaluation to pick the best filter bool False
timeout Maximum amount of time to spend (in milliseconds) on optimizations. Further potential optimizations are skipped if the timeout is exceeded int | None None

filter

Initialize the filter set with any of the following oxipng.RowFilter enum options:

  • oxipng.RowFilter.NoOp
  • oxipng.RowFilter.Sub
  • oxipng.RowFilter.Up
  • oxipng.RowFilter.Average
  • oxipng.RowFilter.Paeth
  • oxipng.RowFilter.Bigrams
  • oxipng.RowFilter.BigEnt
  • oxipng.RowFilter.Brute

interlace

Set interlace to None to keep existing interlacing or to one of following oxipng.Interlacing enum options:

  • oxipng.Interlacing.Off (interlace disabled)
  • oxipng.Interlacing.Adam7 (interlace enabled)

strip

Initialize the strip option with one of the following static methods in the oxipng.StripChunks class.

Method Description
oxipng.StripChunks.none() None
oxipng.StripChunks.strip(set[bytes]) Strip specific chunks
oxipng.StripChunks.safe() Strip chunks that won't affect rendering (all but cICP, iCCP, sRGB, pHYs, acTL, fcTL, fdAT)
oxipng.StripChunks.keep(set[bytes]) Strip all non-critical chunks except these
oxipng.StripChunks.all() Strip all non-critical chunks

deflate

Initialize the deflate option with one of the following static methods in the oxipng.Deflaters class.

Method Description
oxipng.Deflaters.libdeflater(int) Libdeflater with compression level [0-12]
oxipng.Deflaters.zopfli(int) Zopfli with number of compression iterations to do [1-255]

Development

  1. Install Rust
  2. Install Python 3.8+
  3. Install Pipenv
  4. Clone this repository and navigate to it via command line
    git clone https://github.com/nfrasser/pyoxipng.git
    cd pyoxipng
    
  5. Install dependencies
    pipenv install --dev
    
  6. Activate the dev environment
    pipenv shell
    
  7. Build
    maturin develop
    
  8. Run tests
    pytest
    
  9. Format code
    black .
    

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyoxipng-9.0.0.tar.gz (323.1 kB view hashes)

Uploaded Source

Built Distributions

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp312-none-win_amd64.whl (454.7 kB view hashes)

Uploaded CPython 3.12 Windows x86-64

pyoxipng-9.0.0-cp312-none-win32.whl (428.1 kB view hashes)

Uploaded CPython 3.12 Windows x86

pyoxipng-9.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp312-cp312-macosx_11_0_arm64.whl (613.3 kB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

pyoxipng-9.0.0-cp312-cp312-macosx_10_7_x86_64.whl (648.0 kB view hashes)

Uploaded CPython 3.12 macOS 10.7+ x86-64

pyoxipng-9.0.0-cp311-none-win_amd64.whl (453.9 kB view hashes)

Uploaded CPython 3.11 Windows x86-64

pyoxipng-9.0.0-cp311-none-win32.whl (427.0 kB view hashes)

Uploaded CPython 3.11 Windows x86

pyoxipng-9.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp311-cp311-macosx_11_0_arm64.whl (613.1 kB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

pyoxipng-9.0.0-cp311-cp311-macosx_10_7_x86_64.whl (649.1 kB view hashes)

Uploaded CPython 3.11 macOS 10.7+ x86-64

pyoxipng-9.0.0-cp310-none-win_amd64.whl (453.7 kB view hashes)

Uploaded CPython 3.10 Windows x86-64

pyoxipng-9.0.0-cp310-none-win32.whl (427.0 kB view hashes)

Uploaded CPython 3.10 Windows x86

pyoxipng-9.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp310-cp310-macosx_11_0_arm64.whl (613.1 kB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

pyoxipng-9.0.0-cp310-cp310-macosx_10_7_x86_64.whl (649.1 kB view hashes)

Uploaded CPython 3.10 macOS 10.7+ x86-64

pyoxipng-9.0.0-cp39-none-win_amd64.whl (454.4 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

pyoxipng-9.0.0-cp39-none-win32.whl (428.8 kB view hashes)

Uploaded CPython 3.9 Windows x86

pyoxipng-9.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp39-cp39-macosx_11_0_arm64.whl (613.7 kB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

pyoxipng-9.0.0-cp39-cp39-macosx_10_7_x86_64.whl (649.5 kB view hashes)

Uploaded CPython 3.9 macOS 10.7+ x86-64

pyoxipng-9.0.0-cp38-none-win_amd64.whl (454.5 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

pyoxipng-9.0.0-cp38-none-win32.whl (427.6 kB view hashes)

Uploaded CPython 3.8 Windows x86

pyoxipng-9.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

pyoxipng-9.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

pyoxipng-9.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

pyoxipng-9.0.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

pyoxipng-9.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

pyoxipng-9.0.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ i686

pyoxipng-9.0.0-cp38-cp38-macosx_11_0_arm64.whl (613.8 kB view hashes)

Uploaded CPython 3.8 macOS 11.0+ ARM64

pyoxipng-9.0.0-cp38-cp38-macosx_10_7_x86_64.whl (649.1 kB view hashes)

Uploaded CPython 3.8 macOS 10.7+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page