A proof-of-concept implementation of a parallel-decodable PNG format

Overview

mtpng

A parallelized PNG encoder in Rust

by Brion Vibber [email protected]

Background

Compressing PNG files is a relatively slow operation at large image sizes, and can take from half a second to over a second for 4K resolution and beyond. See my blog post series on the subject for more details.

The biggest CPU costs in traditional libpng seem to be the filtering, which is easy to parallelize, and the deflate compression, which can be parallelized in chunks at a slight loss of compression between block boundaries.

pigz is a well-known C implementation of parallelized deflate/gzip compression, and was a strong inspiration for the chunking scheme used here.

I was also inspired by an experimental C++/OpenMP project called png-parallel by Pascal Beyeler, which didn't implement filtering but confirmed the basic theory.

State

Creates correct files in all color formats (input must be pre-packed). Performs well on large files, but needs work for small files and ancillary chunks. Planning API stability soon, but not yet there -- things will change before 1.0.

Goals

Performance:

  • ☑️ MUST be faster than libpng when multi-threaded
  • ☑️ SHOULD be as fast as or faster than libpng when single-threaded

Functionality:

  • ☑️ MUST support all standard color types and depths
  • ☑️ MUST support all standard filter modes
  • ☑️ MUST compress within a few percent as well as libpng
  • MAY achieve better compression than libpng, but MUST NOT do so at the cost of performance
  • ☑️ SHOULD support streaming output
  • MAY support interlacing

Compatibility:

  • MUST have a good Rust API (in progress)
  • MUST have a good C API (in progress)
  • ☑️ MUST work on Linux x86, x86_64
  • ☑️ MUST work on Linux arm, arm64
  • ☑️ SHOULD work on macOS x86_64
  • ☑️ SHOULD work on iOS arm64
  • ☑️ SHOULD work on Windows x86, x86_64
  • ☑️ ️ SHOULD work on Windows arm64

Compression

Compression ratio is a tiny fraction worse than libpng with the dual-4K screenshot and the arch photo at the current default 256 KiB chunk size, getting closer the larger you increase it.

Using a smaller chunk size, or enabling streaming mode, will increase the file size slightly more in exchange for greater parallelism (small chunks) and lower latency to bytes hitting the wire (streaming).

In 0.3.5 a correction was made to the filter heuristic algorithm to match libpng in some circumstances where it differs; this should provide very similar results to libpng when used as a drop-in replacement now. Later research may involve changing the heuristic, as it fails to correctly predict good performance of the "none" filter on many screenshot-style true color images.

Performance

Note that unoptimized debug builds are about 50x slower than optimized release builds. Always run with --release!

As of September 26, 2018 with Rust 1.29.0, single-threaded performance on Linux x86_64 is ~30-40% faster than libpng saving the same dual-4K screenshot sample image on Linux and macOS x86_64. Using multiple threads consistently beats libpng by a lot, and scales reasonably well at least to 8 physical cores.

See docs/perf.md for informal benchmarks on various devices.

At the default settings, files whose uncompressed data is less than 128 KiB will not see any multi-threading gains, but may still run faster than libpng due to faster filtering.

Todos

See the projects list on GitHub for active details.

Usage

Note: the Rust and C APIs are not yet stable, and will change before 1.0.

Rust usage

See the crate API docs for details.

The mtpng CLI tool can be used as an example of writing files.

In short, something like this:

let mut writer = Vec::<u8>::new();

let mut header = Header::new();
header.set_size(640, 480)?;
header.set_color(ColorType::TruecolorAlpha, 8)?;

let mut options = Options::new();

let mut encoder = Encoder::new(writer, &options);

encoder.write_header(&header)?;
encoder.write_image_rows(&data)?;
encoder.finish()?;

C usage

See c/mtpng.h for a C header file which connects to unsafe-Rust wrapper functions in the mtpng::capi module.

To build the C sample on Linux or macOS, run make. On Windows, run build-win.bat x64 for an x86-64 native build, or pass x86 or arm64 to build for those platforms.

These will build a sample executable from sample.c as well as a libmtpng.so, libmtpng.dylib, or mtpng.dll for it to link. It produces an output file in out/csample.png.

Data flow

Encoding can be broken into many parallel blocks:

Encoder data flow diagram

Decoding cannot; it must be run as a stream, but can pipeline (not yet implemented):

Decoder data flow diagram

Dependencies

Rayon is used for its ThreadPool implementation. You can create an encoder using either the default Rayon global pool or a custom ThreadPool instance.

crc is used for calculating PNG chunk checksums.

libz-sys is used to wrap libz for the deflate compression. I briefly looked at pure-Rust implementations but couldn't find any supporting raw stream output, dictionary setting, and flushing to byte boundaries without closing the stream.

itertools is used to manage iteration in the filters.

typenum is used to do compile-time constant specialization via generics.

png is used by the CLI tool to load input files to recompress for testing.

clap is used by the CLI tool to handle option parsing and help display.

time is used by the CLI tool to time compression.

License

You may use this software under the following MIT-style license:

Copyright (c) 2018-2021 Brion Vibber

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Owner
Brion Vibber
MediaWiki, video playback, and other random stuff.
Brion Vibber
Hide sensitive information in images

Data-Preserved Script allowing to blur the most sensitive information on images. Prerequisites Before you begin, ensure you have met the following req

2 Dec 01, 2021
Nutrify - take a photo of food and learn about it

Nutrify - take a photo of food and learn about it Work in progress. To make this a thing, we're going to need lots of food images... Start uploading y

Daniel Bourke 93 Dec 30, 2022
SGTL - Spectral Graph Theory Library

SGTL - Spectral Graph Theory Library SGTL is a python library of spectral graph theory methods. The library is still very new and so there are many fe

Peter Macgregor 6 Oct 01, 2022
Collection of SVG diagrams about how UTF-8 works

Diagrams Repository of diagrams made for articles on my blog. All diagrams are created using diagrams.net. UTF-8 Licenses Copyright 2022 Seth Michael

Seth Michael Larson 24 Aug 13, 2022
MyPaint is a simple drawing and painting program that works well with Wacom-style graphics tablets.

MyPaint A fast and dead-simple painting app for artists Features Infinite canvas Extremely configurable brushes Distraction-free fullscreen mode Exten

MyPaint 2.3k Jan 01, 2023
PyLibTiff - a wrapper to the libtiff library to Python using ctypes

PyLibTiff is a package that provides: a wrapper to the libtiff library to Python using ctypes. a pure Python module for reading and writing TIFF and L

Pearu Peterson 105 Dec 21, 2022
QR code python application which can read(decode) and generate(encode) QR codes.

QR Code Application This is a basic QR Code application. Using this application you can generate QR code for you text/links. Using this application yo

Atharva Parkhe 1 Aug 09, 2022
Deep Illuminator is a data augmentation tool designed for image relighting.

Deep Illuminator Deep Illuminator is a data augmentation tool designed for image relighting. It can be used to easily and efficiently genera

George Chogovadze 52 Nov 29, 2022
Hacking github graph with a easy python script

Hacking-Github-Graph Hacking github graph with a easy python script Requirements git latest version installed. A text editor (eg: vs code, sublime tex

SENPAI LEGEND 1 Nov 01, 2021
Rembg is a tool to remove images background.

Rembg is a tool to remove images background.

Daniel Gatis 7.8k Jan 05, 2023
thumbor is an open-source photo thumbnail service by globo.com

Survey If you use thumbor, please take 1 minute and answer this survey? It's only 2 questions and one is multiple choice!!! thumbor is a smart imaging

Thumbor (by @globocom) 9.3k Dec 31, 2022
A simple image to text converter with GUI!

TEXTEMAGE! Textemage is a quick tool that extracts text from images, it is a Python based GUI program(also available in executable version). This is a

Akascape 5 Oct 26, 2022
A minimal python script for generating bip39 seed phrases, and corresponding Seed Signer Seed seed phrase qr code ready for offline printing.

A minimal python script for generating bip39 seed phrases, and corresponding Seed Signer Seed seed phrase qr code ready for offline printing.

CypherToad 8 Sep 12, 2022
New program to export a Blender model to the LBA2 model format.

LBA2 Blender to Model 2 This is a new program to export a Blender model to the LBA2 model format. This is also the first publicly released version of

2 Nov 30, 2022
Bringing vtk.js into Dash and Python

Dash VTK Dash VTK lets you integrate the vtk.js visualization pipeline directly into your Dash app. It is powered by react-vtk-js. Docs Demo Explorer

Plotly 88 Nov 29, 2022
Convert the SVG code to PNG and replace the line by a call to the image in markdown

Convert the SVG code to PNG and replace the line by a call to the image in markdown

6 Sep 06, 2022
Tools for making image cutouts from sets of TESS full frame images

Cutout tools for astronomical images Astrocut provides tools for making cutouts from sets of astronomical images with shared footprints. It is under a

Space Telescope Science Institute 20 Dec 16, 2022
3D printer / slicing GUI built on top of the Uranium framework

Cura Ultimaker Cura is a state-of-the-art slicer application to prepare your 3D models for printing with a 3D printer. With hundreds of settings and h

Ultimaker 4.4k Jan 02, 2023
Python Script to generate posters out of the images in directory.

Poster-Maker Python Script to generate posters out of the images in directory. This version is very basic ligthweight code to combine organize images

1 Feb 02, 2022
HyperBlend is a new type of hyperspectral image simulator based on Blender.

HyperBlend version 0.1.0 This is the HyperBlend leaf spectra simulator developed in Spectral Laboratory of University of Jyväskylä. You can use and mo

SILMAE 2 Jun 20, 2022