Skip to content

Commit 24524db

Browse files
author
Nick Frasser
authored
Update to oxipng 8 (#9)
* Update to oxipng 8 Fix corresponding APIs * Update types and tests for new options format * Update README and CHANGELOG * Clearer Interlacing None option name NoOp -> Off to indicate that this disables interlacing on output PNG * v8.0.0
1 parent 6109da0 commit 24524db

File tree

9 files changed

+72
-77
lines changed

9 files changed

+72
-77
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 8.0.0
4+
5+
- Update to oxipng 8
6+
- BREAKING: `interlace` option now expects `oxipng.Interlace` enum
7+
- BREAKING: replace `alphas` option with `optimize_alpha` boolean
8+
- Added: `check` option
9+
310
## 7.0.0
411

512
- Upgrade to oxipng 7

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyoxipng"
3-
version = "7.0.0"
3+
version = "8.0.0"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -9,5 +9,5 @@ name = "oxipng"
99
crate-type = ["cdylib"]
1010

1111
[dependencies]
12-
pyo3 = { version = "0.17.2", features = ["extension-module"] }
13-
oxipng = { version = "7.0.*" }
12+
pyo3 = { version = "0.17.3", features = ["extension-module"] }
13+
oxipng = { version = "8.0.*" }

README.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ oxipng.optimize("/path/to/image.png", level=6, backup=True, interlace=1)
7272
| `level` | Set the optimization level to an integer between 0 and 6 (inclusive) | `int` | `2` |
7373
| `backup` | Whether the input file should be backed up before writing the output | `bool` | `False` |
7474
| `fix_errors` | Attempt to fix errors when decoding the input file rather than throwing `PngError` | `bool` | `False` |
75+
| `check` | Don't actually run any optimizations, just parse the PNG file | `bool` | `False` |
7576
| `pretend` | Don't actually write any output file, just calculate the best results | `bool` | `False` |
7677
| `force` | Write to output even if there was no improvement in compression | `bool` | `False` |
7778
| `preserve_attrs` | Ensure the output file has the same permissions as the input file | `bool` | `False` |
7879
| `filter` | Which filters to try on the file. Use Use enum values from `oxipng.RowFilter` | `set=[RowFilter.NoOp]` | `{RowFilter.NoOp}` |
79-
| `interlace` | Whether to change the interlacing type of the file. `0` means disable interlacing. `1` means enable it. `None` means leave as is | `int \| None` | `None` |
80-
| `alphas` | Alpha filtering strategies to use. Use enum values from `oxipng.AlphaOptim` | `set[AlphaOptim]` | `{AlphaOptim.NoOp}` |
80+
| `interlace` | Whether to change the interlacing type of the file. `None` will not change current interlacing type | `Interlacing \| None` | `None` |
81+
| `optimize_alpha` | Whether to allow transparent pixels to be altered to improve compression | `bool` | `False` |
8182
| `bit_depth_reduction` | Whether to attempt bit depth reduction | `bool` | `True` |
8283
| `color_type_reduction` | Whether to attempt color type reduction | `bool` | `True` |
8384
| `palette_reduction` | Whether to attempt palette reduction | `bool` | `True` |
@@ -88,18 +89,6 @@ oxipng.optimize("/path/to/image.png", level=6, backup=True, interlace=1)
8889
| `use_heuristics` | Whether to use heuristics to pick the best filter and compression. Intended for use with `level=1` | `bool` | `False` |
8990
| `timeout` | Maximum amount of time to spend (in milliseconds) on optimizations. Further potential optimizations are skipped if the timeout is exceeded | `int \| None` | `None` |
9091

91-
### alphas
92-
93-
Initialize the `alphas` set with any of the following enum options:
94-
95-
- `oxipng.AlphaOptim.NoOp`
96-
- `oxipng.AlphaOptim.Black`
97-
- `oxipng.AlphaOptim.White`
98-
- `oxipng.AlphaOptim.Up`
99-
- `oxipng.AlphaOptim.Right`
100-
- `oxipng.AlphaOptim.Down`
101-
- `oxipng.AlphaOptim.Left`
102-
10392
### filter
10493

10594
Initialize the `filter` set with any of the following enum options:
@@ -113,6 +102,14 @@ Initialize the `filter` set with any of the following enum options:
113102
- `oxipng.RowFilter.BigEnt`
114103
- `oxipng.RowFilter.Brute`
115104

105+
### interlace
106+
107+
Set `interlace` to `None` to keep existing interlacing or to one of following
108+
enum options:
109+
110+
- `oxipng.Interlacing.Off` (interlace disabled)
111+
- `oxipng.Interlacing.Adam7` (interlace enabled)
112+
116113
### strip
117114

118115
Initialize the `strip` option with one of the following static methods in the

oxipng.pyi

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@ StrOrBytesPath = Union[str, bytes, Path]
1111

1212
class PngError(Exception): ...
1313

14-
class AlphaOptim(Enum):
15-
NoOp = ...
16-
Black = ...
17-
White = ...
18-
Up = ...
19-
Right = ...
20-
Down = ...
21-
Left = ...
22-
2314
class RowFilter(Enum):
2415
NoOp = ...
2516
Sub = ...
@@ -32,6 +23,10 @@ class RowFilter(Enum):
3223
BigEnt = ...
3324
Brute = ...
3425

26+
class Interlacing(Enum):
27+
Off = ...
28+
Adam7 = ...
29+
3530
class Headers:
3631
@staticmethod
3732
def none() -> "Headers": ...
@@ -70,12 +65,13 @@ def optimize(
7065
level: int = 2,
7166
backup: bool = False,
7267
fix_errors: bool = False,
68+
check: bool = False,
7369
pretend: bool = False,
7470
force: bool = False,
7571
preserve_attrs: bool = False,
7672
filter: Set[RowFilter] = {RowFilter.NoOp},
77-
interlace: Optional[int] = None,
78-
alphas: Set[AlphaOptim] = {AlphaOptim.NoOp},
73+
interlace: Optional[Interlacing] = None,
74+
optimize_alpha: bool = False,
7975
bit_depth_reduction: bool = True,
8076
color_type_reduction: bool = True,
8177
palette_reduction: bool = True,
@@ -91,12 +87,13 @@ def optimize_from_memory(
9187
level: int = 2,
9288
backup: bool = False,
9389
fix_errors: bool = False,
90+
check: bool = False,
9491
pretend: bool = False,
9592
force: bool = False,
9693
preserve_attrs: bool = False,
9794
filter: Set[RowFilter] = {RowFilter.NoOp},
98-
interlace: Optional[int] = None,
99-
alphas: Set[AlphaOptim] = {AlphaOptim.NoOp},
95+
interlace: Optional[Interlacing] = None,
96+
optimize_alpha: bool = False,
10097
bit_depth_reduction: bool = True,
10198
color_type_reduction: bool = True,
10299
palette_reduction: bool = True,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "maturin"
55
[project]
66
name = "pyoxipng"
77
requires-python = ">=3.7"
8-
version = "7.0.0"
8+
version = "8.0.0"
99
description = "Python wrapper for multithreaded .png image file optimizer oxipng"
1010
readme = "README.md"
1111
license = { file = "LICENSE" }

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ fn optimize_from_memory(data: &PyBytes, kwds: Option<&PyDict>) -> PyResult<Py<Py
4545
#[pymodule]
4646
fn oxipng(py: Python, m: &PyModule) -> PyResult<()> {
4747
m.add("PngError", py.get_type::<PngError>())?;
48-
m.add_class::<parse::AlphaOptim>()?;
4948
m.add_class::<parse::RowFilter>()?;
49+
m.add_class::<parse::Interlacing>()?;
5050
m.add_class::<parse::Headers>()?;
5151
m.add_class::<parse::Deflaters>()?;
5252
m.add_function(wrap_pyfunction!(optimize, m)?)?;

src/parse.rs

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,6 @@ use op::IndexSet;
1111

1212
use crate::util::*;
1313

14-
// Alpha optimization
15-
#[pyclass]
16-
#[derive(Clone, Debug)]
17-
pub enum AlphaOptim {
18-
NoOp = op::AlphaOptim::NoOp as isize,
19-
Black = op::AlphaOptim::Black as isize,
20-
White = op::AlphaOptim::White as isize,
21-
Up = op::AlphaOptim::Up as isize,
22-
Right = op::AlphaOptim::Right as isize,
23-
Down = op::AlphaOptim::Down as isize,
24-
Left = op::AlphaOptim::Left as isize,
25-
}
26-
27-
#[pymethods]
28-
impl AlphaOptim {
29-
fn __hash__(&self) -> u64 {
30-
let mut hasher = DefaultHasher::new();
31-
(self.clone() as u64).hash(&mut hasher);
32-
hasher.finish()
33-
}
34-
}
35-
36-
impl From<AlphaOptim> for op::AlphaOptim {
37-
fn from(val: AlphaOptim) -> Self {
38-
match val {
39-
AlphaOptim::NoOp => Self::NoOp,
40-
AlphaOptim::Black => Self::Black,
41-
AlphaOptim::White => Self::White,
42-
AlphaOptim::Up => Self::Up,
43-
AlphaOptim::Right => Self::Right,
44-
AlphaOptim::Down => Self::Down,
45-
AlphaOptim::Left => Self::Left,
46-
}
47-
}
48-
}
49-
5014
// Filter
5115
#[pyclass]
5216
#[derive(Clone, Debug)]
@@ -89,6 +53,32 @@ impl From<RowFilter> for op::RowFilter {
8953
}
9054
}
9155

56+
// Interlacing
57+
#[pyclass]
58+
#[derive(Clone, Debug)]
59+
pub enum Interlacing {
60+
Off = op::Interlacing::None as isize,
61+
Adam7 = op::Interlacing::Adam7 as isize,
62+
}
63+
64+
#[pymethods]
65+
impl Interlacing {
66+
fn __hash__(&self) -> u64 {
67+
let mut hasher = DefaultHasher::new();
68+
(self.clone() as u64).hash(&mut hasher);
69+
hasher.finish()
70+
}
71+
}
72+
73+
impl From<Interlacing> for op::Interlacing {
74+
fn from(val: Interlacing) -> Self {
75+
match val {
76+
Interlacing::Off => Self::None,
77+
Interlacing::Adam7 => Self::Adam7,
78+
}
79+
}
80+
}
81+
9282
#[pyclass]
9383
#[derive(Debug, Clone)]
9484
pub struct Headers(pub op::Headers);
@@ -204,18 +194,22 @@ fn parse_kw_opt(key: &str, value: &PyAny, opts: &mut op::Options) -> PyResult<()
204194
"level" => {} // Handled elsewhere, ignore
205195
"backup" => opts.backup = value.downcast::<PyBool>()?.is_true(),
206196
"fix_errors" => opts.fix_errors = value.downcast::<PyBool>()?.is_true(),
197+
"check" => opts.check = value.downcast::<PyBool>()?.is_true(),
207198
"pretend" => opts.pretend = value.downcast::<PyBool>()?.is_true(),
208199
"force" => opts.force = value.downcast::<PyBool>()?.is_true(),
209200
"preserve_attrs" => opts.preserve_attrs = value.downcast::<PyBool>()?.is_true(),
210201
"filter" => {
211202
opts.filter =
212203
py_iter_extract_map::<RowFilter, op::RowFilter, IndexSet<op::RowFilter>>(value)?
213204
}
214-
"interlace" => opts.interlace = py_option(value)?,
215-
"alphas" => {
216-
opts.alphas =
217-
py_iter_extract_map::<AlphaOptim, op::AlphaOptim, IndexSet<op::AlphaOptim>>(value)?
205+
"interlace" => {
206+
opts.interlace = if let Some(i) = py_option::<Interlacing>(value)? {
207+
Some(i.into())
208+
} else {
209+
None
210+
}
218211
}
212+
"optimize_alpha" => opts.optimize_alpha = value.downcast::<PyBool>()?.is_true(),
219213
"bit_depth_reduction" => opts.bit_depth_reduction = value.downcast::<PyBool>()?.is_true(),
220214
"color_type_reduction" => opts.color_type_reduction = value.downcast::<PyBool>()?.is_true(),
221215
"palette_reduction" => opts.palette_reduction = value.downcast::<PyBool>()?.is_true(),

test/test_oxipng.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ def test_optimize_opts(infile, bakfile):
5858
force=True,
5959
preserve_attrs=True,
6060
filter={oxipng.RowFilter.Sub, oxipng.RowFilter.Up, oxipng.RowFilter.Average},
61-
interlace=1,
62-
alphas={oxipng.AlphaOptim.White},
61+
interlace=oxipng.Interlacing.Adam7,
62+
optimize_alpha=True,
6363
bit_depth_reduction=False,
6464
palette_reduction=False,
6565
grayscale_reduction=False,

0 commit comments

Comments
 (0)