colopresso 12.2.0__cp310-abi3-win_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- colopresso/__init__.py +56 -0
- colopresso/_colopresso.pyd +0 -0
- colopresso/_colopresso_ext.c +612 -0
- colopresso/core.py +266 -0
- colopresso/py.typed +65 -0
- colopresso-12.2.0.dist-info/METADATA +669 -0
- colopresso-12.2.0.dist-info/RECORD +8 -0
- colopresso-12.2.0.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: colopresso
|
|
3
|
+
Version: 12.2.0
|
|
4
|
+
Summary: PNG conversion and compression library
|
|
5
|
+
Author: COLOPL, Inc.
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
+
Classifier: Operating System :: MacOS
|
|
11
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
21
|
+
Requires-Dist: pillow>=10.0; extra == "dev"
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Colopresso Python Bindings
|
|
25
|
+
|
|
26
|
+
Python bindings for the colopresso image compression library. Encode PNG images to WebP, AVIF, or optimized PNG (PNGX) formats.
|
|
27
|
+
|
|
28
|
+
## Table of Contents
|
|
29
|
+
|
|
30
|
+
- [Requirements](#requirements)
|
|
31
|
+
- [Installation](#installation)
|
|
32
|
+
- [Quick Start](#quick-start)
|
|
33
|
+
- [API Reference](#api-reference)
|
|
34
|
+
- [Encoding Functions](#encoding-functions)
|
|
35
|
+
- [Config Class](#config-class)
|
|
36
|
+
- [PngxLossyType Enum](#pngxlossytype-enum)
|
|
37
|
+
- [Configuration Parameters](#configuration-parameters)
|
|
38
|
+
- [Utility Functions](#utility-functions)
|
|
39
|
+
- [Exception Classes](#exception-classes)
|
|
40
|
+
- [Examples](#examples)
|
|
41
|
+
- [Building Wheels](#building-wheels)
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
> [!IMPORTANT]
|
|
46
|
+
> **AVX2 instruction set support is required on x86_64 (amd64) platforms.**
|
|
47
|
+
> Intel Haswell (2013) or later, or AMD Excavator or later processors are required.
|
|
48
|
+
|
|
49
|
+
| Platform | Architecture | Requirements |
|
|
50
|
+
|----------|--------------|--------------|
|
|
51
|
+
| Windows | x64 | AVX2 support |
|
|
52
|
+
| Windows | ARM64 | NEON (ASIMD) |
|
|
53
|
+
| macOS | x86_64 | AVX2 support |
|
|
54
|
+
| macOS | arm64 (Apple Silicon) | NEON (ASIMD) |
|
|
55
|
+
| Linux (glibc) | x86_64 | AVX2 support |
|
|
56
|
+
| Linux (glibc) | aarch64 | NEON (ASIMD) |
|
|
57
|
+
| Linux (musl) | x86_64 | AVX2 support |
|
|
58
|
+
| Linux (musl) | aarch64 | NEON (ASIMD) |
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
### From PyPI
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install "colopresso"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### From source (requires CMake, Rust, and C compiler)
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd python
|
|
72
|
+
pip install .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Development installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
cd python
|
|
79
|
+
pip install -e ".[dev]"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Quick Start
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
import colopresso
|
|
86
|
+
|
|
87
|
+
# Read PNG file
|
|
88
|
+
with open("input.png", "rb") as f:
|
|
89
|
+
png_data = f.read()
|
|
90
|
+
|
|
91
|
+
# Convert to WebP
|
|
92
|
+
webp_data = colopresso.encode_webp(png_data)
|
|
93
|
+
with open("output.webp", "wb") as f:
|
|
94
|
+
f.write(webp_data)
|
|
95
|
+
|
|
96
|
+
# Convert to AVIF
|
|
97
|
+
avif_data = colopresso.encode_avif(png_data)
|
|
98
|
+
with open("output.avif", "wb") as f:
|
|
99
|
+
f.write(avif_data)
|
|
100
|
+
|
|
101
|
+
# Optimize PNG
|
|
102
|
+
optimized_png = colopresso.encode_pngx(png_data)
|
|
103
|
+
with open("output.png", "wb") as f:
|
|
104
|
+
f.write(optimized_png)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## API Reference
|
|
110
|
+
|
|
111
|
+
### Encoding Functions
|
|
112
|
+
|
|
113
|
+
#### `encode_webp(png_data, config=None) -> bytes`
|
|
114
|
+
|
|
115
|
+
Encode PNG data to WebP format.
|
|
116
|
+
|
|
117
|
+
**Parameters:**
|
|
118
|
+
- `png_data` (bytes): Raw PNG file data
|
|
119
|
+
- `config` (Config, optional): Encoding configuration. Uses defaults if not provided.
|
|
120
|
+
|
|
121
|
+
**Returns:**
|
|
122
|
+
- bytes: WebP encoded data
|
|
123
|
+
|
|
124
|
+
**Raises:**
|
|
125
|
+
- `ColopressoError`: If encoding fails
|
|
126
|
+
|
|
127
|
+
**Example:**
|
|
128
|
+
```python
|
|
129
|
+
import colopresso
|
|
130
|
+
|
|
131
|
+
with open("input.png", "rb") as f:
|
|
132
|
+
png_data = f.read()
|
|
133
|
+
|
|
134
|
+
# Default settings
|
|
135
|
+
webp_data = colopresso.encode_webp(png_data)
|
|
136
|
+
|
|
137
|
+
# Custom quality
|
|
138
|
+
config = colopresso.Config(webp_quality=90.0)
|
|
139
|
+
webp_data = colopresso.encode_webp(png_data, config)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
#### `encode_avif(png_data, config=None) -> bytes`
|
|
145
|
+
|
|
146
|
+
Encode PNG data to AVIF format.
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
- `png_data` (bytes): Raw PNG file data
|
|
150
|
+
- `config` (Config, optional): Encoding configuration. Uses defaults if not provided.
|
|
151
|
+
|
|
152
|
+
**Returns:**
|
|
153
|
+
- bytes: AVIF encoded data
|
|
154
|
+
|
|
155
|
+
**Raises:**
|
|
156
|
+
- `ColopressoError`: If encoding fails (including when output is larger than input)
|
|
157
|
+
|
|
158
|
+
**Example:**
|
|
159
|
+
```python
|
|
160
|
+
import colopresso
|
|
161
|
+
|
|
162
|
+
with open("input.png", "rb") as f:
|
|
163
|
+
png_data = f.read()
|
|
164
|
+
|
|
165
|
+
config = colopresso.Config(avif_quality=70.0, avif_speed=4)
|
|
166
|
+
avif_data = colopresso.encode_avif(png_data, config)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
#### `encode_pngx(png_data, config=None) -> bytes`
|
|
172
|
+
|
|
173
|
+
Optimize PNG data using the PNGX encoder. Supports both lossless and lossy compression.
|
|
174
|
+
|
|
175
|
+
**Parameters:**
|
|
176
|
+
- `png_data` (bytes): Raw PNG file data
|
|
177
|
+
- `config` (Config, optional): Encoding configuration. Uses defaults if not provided.
|
|
178
|
+
|
|
179
|
+
**Returns:**
|
|
180
|
+
- bytes: Optimized PNG data
|
|
181
|
+
|
|
182
|
+
**Raises:**
|
|
183
|
+
- `ColopressoError`: If encoding fails
|
|
184
|
+
|
|
185
|
+
**Example:**
|
|
186
|
+
```python
|
|
187
|
+
import colopresso
|
|
188
|
+
|
|
189
|
+
with open("input.png", "rb") as f:
|
|
190
|
+
png_data = f.read()
|
|
191
|
+
|
|
192
|
+
# 256-color palette optimization
|
|
193
|
+
config = colopresso.Config(
|
|
194
|
+
pngx_lossy_enable=True,
|
|
195
|
+
pngx_lossy_type=colopresso.PngxLossyType.PALETTE256,
|
|
196
|
+
pngx_lossy_max_colors=256
|
|
197
|
+
)
|
|
198
|
+
optimized = colopresso.encode_pngx(png_data, config)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### Config Class
|
|
204
|
+
|
|
205
|
+
The `Config` dataclass holds all encoder settings.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
@dataclass
|
|
209
|
+
class Config:
|
|
210
|
+
# WebP settings
|
|
211
|
+
webp_quality: float = 80.0
|
|
212
|
+
webp_lossless: bool = False
|
|
213
|
+
webp_method: int = 6
|
|
214
|
+
|
|
215
|
+
# AVIF settings
|
|
216
|
+
avif_quality: float = 50.0
|
|
217
|
+
avif_alpha_quality: int = 100
|
|
218
|
+
avif_lossless: bool = False
|
|
219
|
+
avif_speed: int = 6
|
|
220
|
+
avif_threads: int = 1
|
|
221
|
+
|
|
222
|
+
# PNGX settings
|
|
223
|
+
pngx_level: int = 5
|
|
224
|
+
pngx_strip_safe: bool = True
|
|
225
|
+
pngx_optimize_alpha: bool = True
|
|
226
|
+
pngx_lossy_enable: bool = True
|
|
227
|
+
pngx_lossy_type: PngxLossyType = PngxLossyType.PALETTE256
|
|
228
|
+
pngx_lossy_max_colors: int = 256
|
|
229
|
+
pngx_lossy_quality_min: int = 80
|
|
230
|
+
pngx_lossy_quality_max: int = 95
|
|
231
|
+
pngx_lossy_speed: int = 3
|
|
232
|
+
pngx_lossy_dither_level: float = 0.6
|
|
233
|
+
pngx_threads: int = 1
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### PngxLossyType Enum
|
|
239
|
+
|
|
240
|
+
Specifies the type of lossy compression for PNGX.
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
class PngxLossyType(IntEnum):
|
|
244
|
+
PALETTE256 = 0 # 256-color indexed palette
|
|
245
|
+
LIMITED_RGBA4444 = 1 # RGBA4444 limited (16-bit color)
|
|
246
|
+
REDUCED_RGBA32 = 2 # Reduced color RGBA32
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Value | Description | Use Case |
|
|
250
|
+
|---|---|---|
|
|
251
|
+
| `PALETTE256` | Convert to 256-color indexed palette | Icons, illustrations with few colors |
|
|
252
|
+
| `LIMITED_RGBA4444` | Limit each RGBA channel to 4 bits | Prevents banding artifacts in RGBA16bit and RGBA4444 |
|
|
253
|
+
| `REDUCED_RGBA32` | Reduce colors while keeping RGBA32 | When PALETTE256 is not acceptable |
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### Configuration Parameters
|
|
258
|
+
|
|
259
|
+
#### WebP Settings
|
|
260
|
+
|
|
261
|
+
| Parameter | Type | Default | Description |
|
|
262
|
+
|---|---|---|---|
|
|
263
|
+
| `webp_quality` | float | 80.0 | Quality (0.0-100.0). Higher = better quality, larger size |
|
|
264
|
+
| `webp_lossless` | bool | False | True: lossless compression, False: lossy compression |
|
|
265
|
+
| `webp_method` | int | 6 | Compression method (0-6). Higher = better compression, slower |
|
|
266
|
+
|
|
267
|
+
**Advanced WebP Parameters:**
|
|
268
|
+
|
|
269
|
+
| Parameter | Type | Default | Description |
|
|
270
|
+
|---|---|---|---|
|
|
271
|
+
| `webp_target_size` | int | 0 | Target file size in bytes. 0 = disabled |
|
|
272
|
+
| `webp_target_psnr` | float | 0.0 | Target PSNR in dB. 0 = disabled |
|
|
273
|
+
| `webp_segments` | int | 4 | Number of segments (1-4) |
|
|
274
|
+
| `webp_sns_strength` | int | 50 | Spatial noise shaping strength (0-100) |
|
|
275
|
+
| `webp_filter_strength` | int | 60 | Deblocking filter strength (0-100) |
|
|
276
|
+
| `webp_filter_sharpness` | int | 0 | Filter sharpness (0-7). 0 = sharpest |
|
|
277
|
+
| `webp_filter_type` | int | 1 | Filter type. 0 = simple, 1 = strong |
|
|
278
|
+
| `webp_autofilter` | bool | True | Auto-adjust filter strength |
|
|
279
|
+
| `webp_alpha_compression` | bool | True | Compress alpha channel |
|
|
280
|
+
| `webp_alpha_filtering` | int | 1 | Alpha filtering (0-2) |
|
|
281
|
+
| `webp_alpha_quality` | int | 100 | Alpha channel quality (0-100) |
|
|
282
|
+
| `webp_pass` | int | 1 | Number of encoding passes (1-10) |
|
|
283
|
+
| `webp_preprocessing` | int | 0 | Preprocessing. 0=none, 1=segment-smooth, 2=pseudo-random dither |
|
|
284
|
+
| `webp_partitions` | int | 0 | Number of partitions (0-3) |
|
|
285
|
+
| `webp_partition_limit` | int | 0 | Partition size limit (0-100) |
|
|
286
|
+
| `webp_emulate_jpeg_size` | bool | False | Emulate JPEG output size |
|
|
287
|
+
| `webp_thread_level` | int | 0 | Thread level (0-1) |
|
|
288
|
+
| `webp_low_memory` | bool | False | Low memory mode |
|
|
289
|
+
| `webp_near_lossless` | int | 100 | Near-lossless preprocessing (0-100). 100 = off |
|
|
290
|
+
| `webp_exact` | bool | False | Preserve RGB values in transparent areas |
|
|
291
|
+
| `webp_use_delta_palette` | bool | False | Use delta palette (experimental) |
|
|
292
|
+
| `webp_use_sharp_yuv` | bool | False | Use sharp RGB to YUV conversion |
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
#### AVIF Settings
|
|
297
|
+
|
|
298
|
+
| Parameter | Type | Default | Description |
|
|
299
|
+
|---|---|---|---|
|
|
300
|
+
| `avif_quality` | float | 50.0 | Quality (0.0-100.0). Higher = better quality, larger size |
|
|
301
|
+
| `avif_alpha_quality` | int | 100 | Alpha channel quality (0-100) |
|
|
302
|
+
| `avif_lossless` | bool | False | True: lossless compression, False: lossy compression |
|
|
303
|
+
| `avif_speed` | int | 6 | Encoding speed (0-10). 0 = best quality/slowest, 10 = lowest quality/fastest |
|
|
304
|
+
| `avif_threads` | int | 1 | Number of threads for encoding |
|
|
305
|
+
|
|
306
|
+
**Recommended Settings:**
|
|
307
|
+
|
|
308
|
+
| Use Case | quality | speed | Description |
|
|
309
|
+
|---|---|---|---|
|
|
310
|
+
| High Quality | 80-90 | 4 | High quality web images |
|
|
311
|
+
| Balanced | 50-60 | 6 | General purpose |
|
|
312
|
+
| Fast | 40-50 | 8-10 | Batch processing, previews |
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
#### PNGX Settings
|
|
317
|
+
|
|
318
|
+
##### Basic Settings
|
|
319
|
+
|
|
320
|
+
| Parameter | Type | Default | Description |
|
|
321
|
+
|---|---|---|---|
|
|
322
|
+
| `pngx_level` | int | 5 | Compression level (1-6). Higher = better compression |
|
|
323
|
+
| `pngx_strip_safe` | bool | True | Remove safely removable metadata |
|
|
324
|
+
| `pngx_optimize_alpha` | bool | True | Optimize color info in transparent pixels |
|
|
325
|
+
| `pngx_threads` | int | 1 | Number of threads for processing |
|
|
326
|
+
|
|
327
|
+
##### Lossy Compression Settings
|
|
328
|
+
|
|
329
|
+
| Parameter | Type | Default | Description |
|
|
330
|
+
|---|---|---|---|
|
|
331
|
+
| `pngx_lossy_enable` | bool | True | Enable lossy compression |
|
|
332
|
+
| `pngx_lossy_type` | PngxLossyType | PALETTE256 | Type of lossy compression |
|
|
333
|
+
| `pngx_lossy_max_colors` | int | 256 | Maximum colors for palette mode (2-256) |
|
|
334
|
+
| `pngx_lossy_quality_min` | int | 80 | Minimum quality (0-100) |
|
|
335
|
+
| `pngx_lossy_quality_max` | int | 95 | Maximum quality (0-100) |
|
|
336
|
+
| `pngx_lossy_speed` | int | 3 | Quantization speed (1-10). Higher = faster, lower quality |
|
|
337
|
+
| `pngx_lossy_dither_level` | float | 0.6 | Dithering strength (0.0-1.0) |
|
|
338
|
+
|
|
339
|
+
##### PALETTE256 Mode Settings
|
|
340
|
+
|
|
341
|
+
| Parameter | Type | Default | Description |
|
|
342
|
+
|---|---|---|---|
|
|
343
|
+
| `pngx_lossy_reduced_colors` | int | -1 | Target color count after reduction. -1 = auto |
|
|
344
|
+
| `pngx_saliency_map_enable` | bool | True | Adaptive quantization using saliency map |
|
|
345
|
+
| `pngx_chroma_anchor_enable` | bool | True | Preserve chroma anchor points |
|
|
346
|
+
| `pngx_adaptive_dither_enable` | bool | True | Adaptive dithering |
|
|
347
|
+
| `pngx_gradient_boost_enable` | bool | True | Gradient enhancement |
|
|
348
|
+
| `pngx_chroma_weight_enable` | bool | True | Apply chroma weighting |
|
|
349
|
+
| `pngx_postprocess_smooth_enable` | bool | True | Post-processing smoothing |
|
|
350
|
+
| `pngx_postprocess_smooth_importance_cutoff` | float | 0.6 | Smoothing importance cutoff |
|
|
351
|
+
| `pngx_palette256_gradient_profile_enable` | bool | True | Enable gradient profile |
|
|
352
|
+
| `pngx_palette256_gradient_dither_floor` | float | 0.78 | Gradient dither floor |
|
|
353
|
+
| `pngx_palette256_alpha_bleed_enable` | bool | False | Enable alpha bleed |
|
|
354
|
+
| `pngx_palette256_alpha_bleed_max_distance` | int | 64 | Maximum bleed distance in pixels |
|
|
355
|
+
| `pngx_palette256_alpha_bleed_opaque_threshold` | int | 248 | Opaque threshold |
|
|
356
|
+
| `pngx_palette256_alpha_bleed_soft_limit` | int | 160 | Soft bleed limit |
|
|
357
|
+
|
|
358
|
+
##### LIMITED_RGBA4444 Mode Settings
|
|
359
|
+
|
|
360
|
+
| Parameter | Type | Default | Description |
|
|
361
|
+
|---|---|---|---|
|
|
362
|
+
| `pngx_lossy_reduced_bits_rgb` | int | 4 | RGB channel bit depth (1-8) |
|
|
363
|
+
| `pngx_lossy_reduced_alpha_bits` | int | 4 | Alpha channel bit depth (1-8) |
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### Utility Functions
|
|
368
|
+
|
|
369
|
+
#### Version Information
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
def get_version() -> int
|
|
373
|
+
```
|
|
374
|
+
Get the colopresso version number.
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
def get_libwebp_version() -> int
|
|
378
|
+
```
|
|
379
|
+
Get the libwebp version number (e.g., 67072 = 1.4.0).
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
def get_libpng_version() -> int
|
|
383
|
+
```
|
|
384
|
+
Get the libpng version number.
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
def get_libavif_version() -> int
|
|
388
|
+
```
|
|
389
|
+
Get the libavif version number.
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
def get_pngx_oxipng_version() -> int
|
|
393
|
+
```
|
|
394
|
+
Get the oxipng version number.
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
def get_pngx_libimagequant_version() -> int
|
|
398
|
+
```
|
|
399
|
+
Get the libimagequant version number.
|
|
400
|
+
|
|
401
|
+
#### Build Information
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
def get_buildtime() -> int
|
|
405
|
+
```
|
|
406
|
+
Get the build timestamp (Unix time).
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
def get_compiler_version_string() -> str
|
|
410
|
+
```
|
|
411
|
+
Get the C compiler version string.
|
|
412
|
+
|
|
413
|
+
```python
|
|
414
|
+
def get_rust_version_string() -> str
|
|
415
|
+
```
|
|
416
|
+
Get the Rust compiler version string.
|
|
417
|
+
|
|
418
|
+
#### Thread Information
|
|
419
|
+
|
|
420
|
+
```python
|
|
421
|
+
def is_threads_enabled() -> bool
|
|
422
|
+
```
|
|
423
|
+
Check if multithreading is enabled.
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
def get_default_thread_count() -> int
|
|
427
|
+
```
|
|
428
|
+
Get the default number of threads.
|
|
429
|
+
|
|
430
|
+
```python
|
|
431
|
+
def get_max_thread_count() -> int
|
|
432
|
+
```
|
|
433
|
+
Get the maximum available thread count.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
### Exception Classes
|
|
438
|
+
|
|
439
|
+
#### ColopressoError
|
|
440
|
+
|
|
441
|
+
```python
|
|
442
|
+
class ColopressoError(Exception):
|
|
443
|
+
code: int # Error code
|
|
444
|
+
message: str # Error message
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Error Codes:**
|
|
448
|
+
|
|
449
|
+
| Code | Name | Description |
|
|
450
|
+
|---|---|---|
|
|
451
|
+
| 0 | OK | Success |
|
|
452
|
+
| 1 | File not found | File not found |
|
|
453
|
+
| 2 | Invalid PNG | Invalid PNG data |
|
|
454
|
+
| 3 | Invalid format | Invalid format |
|
|
455
|
+
| 4 | Out of memory | Memory allocation failed |
|
|
456
|
+
| 5 | Encode failed | Encoding failed |
|
|
457
|
+
| 6 | Decode failed | Decoding failed |
|
|
458
|
+
| 7 | IO error | Input/output error |
|
|
459
|
+
| 8 | Invalid parameter | Invalid parameter |
|
|
460
|
+
| 9 | Output not smaller | Output is not smaller than input |
|
|
461
|
+
|
|
462
|
+
**Example:**
|
|
463
|
+
```python
|
|
464
|
+
import colopresso
|
|
465
|
+
|
|
466
|
+
try:
|
|
467
|
+
result = colopresso.encode_avif(png_data)
|
|
468
|
+
except colopresso.ColopressoError as e:
|
|
469
|
+
if e.code == 9:
|
|
470
|
+
print("AVIF compression was not effective. Using original PNG.")
|
|
471
|
+
else:
|
|
472
|
+
print(f"Error: {e.message}")
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Examples
|
|
478
|
+
|
|
479
|
+
### WebP Conversion with Quality Settings
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
import colopresso
|
|
483
|
+
|
|
484
|
+
with open("photo.png", "rb") as f:
|
|
485
|
+
png_data = f.read()
|
|
486
|
+
|
|
487
|
+
# High quality WebP
|
|
488
|
+
config = colopresso.Config(
|
|
489
|
+
webp_quality=95.0,
|
|
490
|
+
webp_method=6,
|
|
491
|
+
webp_use_sharp_yuv=True
|
|
492
|
+
)
|
|
493
|
+
high_quality = colopresso.encode_webp(png_data, config)
|
|
494
|
+
|
|
495
|
+
# High compression WebP
|
|
496
|
+
config = colopresso.Config(
|
|
497
|
+
webp_quality=60.0,
|
|
498
|
+
webp_method=6
|
|
499
|
+
)
|
|
500
|
+
compressed = colopresso.encode_webp(png_data, config)
|
|
501
|
+
|
|
502
|
+
# Lossless WebP
|
|
503
|
+
config = colopresso.Config(webp_lossless=True)
|
|
504
|
+
lossless = colopresso.encode_webp(png_data, config)
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### AVIF with Multithreading
|
|
508
|
+
|
|
509
|
+
```python
|
|
510
|
+
import colopresso
|
|
511
|
+
|
|
512
|
+
with open("large_image.png", "rb") as f:
|
|
513
|
+
png_data = f.read()
|
|
514
|
+
|
|
515
|
+
# Multithreaded high-speed encoding
|
|
516
|
+
config = colopresso.Config(
|
|
517
|
+
avif_quality=70.0,
|
|
518
|
+
avif_speed=6,
|
|
519
|
+
avif_threads=4
|
|
520
|
+
)
|
|
521
|
+
avif_data = colopresso.encode_avif(png_data, config)
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### PNG Optimization (256-Color Palette)
|
|
525
|
+
|
|
526
|
+
```python
|
|
527
|
+
import colopresso
|
|
528
|
+
|
|
529
|
+
with open("icon.png", "rb") as f:
|
|
530
|
+
png_data = f.read()
|
|
531
|
+
|
|
532
|
+
config = colopresso.Config(
|
|
533
|
+
pngx_lossy_enable=True,
|
|
534
|
+
pngx_lossy_type=colopresso.PngxLossyType.PALETTE256,
|
|
535
|
+
pngx_lossy_max_colors=256,
|
|
536
|
+
pngx_lossy_quality_min=85,
|
|
537
|
+
pngx_lossy_quality_max=100,
|
|
538
|
+
pngx_lossy_dither_level=0.8
|
|
539
|
+
)
|
|
540
|
+
optimized = colopresso.encode_pngx(png_data, config)
|
|
541
|
+
|
|
542
|
+
print(f"Original: {len(png_data)} bytes")
|
|
543
|
+
print(f"Optimized: {len(optimized)} bytes")
|
|
544
|
+
print(f"Reduction: {(1 - len(optimized)/len(png_data))*100:.1f}%")
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### PNG Lossless Optimization
|
|
548
|
+
|
|
549
|
+
```python
|
|
550
|
+
import colopresso
|
|
551
|
+
|
|
552
|
+
with open("screenshot.png", "rb") as f:
|
|
553
|
+
png_data = f.read()
|
|
554
|
+
|
|
555
|
+
config = colopresso.Config(
|
|
556
|
+
pngx_lossy_enable=False, # Disable lossy compression
|
|
557
|
+
pngx_level=6, # Maximum compression level
|
|
558
|
+
pngx_strip_safe=True, # Remove metadata
|
|
559
|
+
pngx_optimize_alpha=True # Optimize alpha
|
|
560
|
+
)
|
|
561
|
+
optimized = colopresso.encode_pngx(png_data, config)
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Game Texture PNG (RGBA4444)
|
|
565
|
+
|
|
566
|
+
```python
|
|
567
|
+
import colopresso
|
|
568
|
+
|
|
569
|
+
with open("texture.png", "rb") as f:
|
|
570
|
+
png_data = f.read()
|
|
571
|
+
|
|
572
|
+
# RGBA4444 format (16-bit color)
|
|
573
|
+
config = colopresso.Config(
|
|
574
|
+
pngx_lossy_enable=True,
|
|
575
|
+
pngx_lossy_type=colopresso.PngxLossyType.LIMITED_RGBA4444,
|
|
576
|
+
pngx_lossy_reduced_bits_rgb=4,
|
|
577
|
+
pngx_lossy_reduced_alpha_bits=4
|
|
578
|
+
)
|
|
579
|
+
optimized = colopresso.encode_pngx(png_data, config)
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Batch Processing
|
|
583
|
+
|
|
584
|
+
```python
|
|
585
|
+
import colopresso
|
|
586
|
+
from pathlib import Path
|
|
587
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
588
|
+
|
|
589
|
+
def convert_to_webp(png_path: Path) -> tuple[Path, int, int]:
|
|
590
|
+
"""Convert PNG to WebP and return size info"""
|
|
591
|
+
with open(png_path, "rb") as f:
|
|
592
|
+
png_data = f.read()
|
|
593
|
+
|
|
594
|
+
config = colopresso.Config(webp_quality=80.0)
|
|
595
|
+
webp_data = colopresso.encode_webp(png_data, config)
|
|
596
|
+
|
|
597
|
+
webp_path = png_path.with_suffix(".webp")
|
|
598
|
+
with open(webp_path, "wb") as f:
|
|
599
|
+
f.write(webp_data)
|
|
600
|
+
|
|
601
|
+
return webp_path, len(png_data), len(webp_data)
|
|
602
|
+
|
|
603
|
+
# Parallel conversion
|
|
604
|
+
png_files = list(Path("images").glob("*.png"))
|
|
605
|
+
with ThreadPoolExecutor(max_workers=4) as executor:
|
|
606
|
+
results = list(executor.map(convert_to_webp, png_files))
|
|
607
|
+
|
|
608
|
+
for path, original, converted in results:
|
|
609
|
+
print(f"{path.name}: {original} -> {converted} ({(1-converted/original)*100:.1f}% reduction)")
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Error Handling
|
|
613
|
+
|
|
614
|
+
```python
|
|
615
|
+
import colopresso
|
|
616
|
+
|
|
617
|
+
def safe_encode(png_data: bytes, format: str = "webp") -> bytes | None:
|
|
618
|
+
"""Encode with error handling"""
|
|
619
|
+
config = colopresso.Config()
|
|
620
|
+
|
|
621
|
+
try:
|
|
622
|
+
if format == "webp":
|
|
623
|
+
return colopresso.encode_webp(png_data, config)
|
|
624
|
+
elif format == "avif":
|
|
625
|
+
return colopresso.encode_avif(png_data, config)
|
|
626
|
+
elif format == "pngx":
|
|
627
|
+
return colopresso.encode_pngx(png_data, config)
|
|
628
|
+
else:
|
|
629
|
+
raise ValueError(f"Unknown format: {format}")
|
|
630
|
+
|
|
631
|
+
except colopresso.ColopressoError as e:
|
|
632
|
+
if e.code == 2:
|
|
633
|
+
print("Error: Input is not a valid PNG")
|
|
634
|
+
elif e.code == 9:
|
|
635
|
+
print(f"{format.upper()} compression was not effective")
|
|
636
|
+
return png_data # Return original data
|
|
637
|
+
else:
|
|
638
|
+
print(f"Encoding error: {e.message}")
|
|
639
|
+
return None
|
|
640
|
+
|
|
641
|
+
# Usage
|
|
642
|
+
with open("input.png", "rb") as f:
|
|
643
|
+
png_data = f.read()
|
|
644
|
+
|
|
645
|
+
result = safe_encode(png_data, "avif")
|
|
646
|
+
if result:
|
|
647
|
+
with open("output.avif", "wb") as f:
|
|
648
|
+
f.write(result)
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## Building Wheels
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
cd python
|
|
657
|
+
pip install build
|
|
658
|
+
python -m build --wheel
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
The wheel will be created in `python/dist/`.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## License
|
|
666
|
+
|
|
667
|
+
colopresso is licensed under GPL-3.0-or-later.
|
|
668
|
+
|
|
669
|
+
Copyright (C) 2026 COLOPL, Inc.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
colopresso/__init__.py,sha256=tga5NFjmtRR0iuM0K8qBXtA-Rfq9_pdwcEhPtREt9nE,1238
|
|
2
|
+
colopresso/_colopresso.pyd,sha256=tm_u9JFcgB1ITTa1qKgTjwq4aTtK57Pob8huBPRuD4g,13815296
|
|
3
|
+
colopresso/_colopresso_ext.c,sha256=5QlOnXm8dQqz_0xdReQDHnzyjUDccc1Z1w-cCFXdUt8,23930
|
|
4
|
+
colopresso/core.py,sha256=Mv_XUZ1-hM0eUBrmqjWUwgUil_s1zzWgFD0JSvLbBe4,7985
|
|
5
|
+
colopresso/py.typed,sha256=i3wkBOk9Q7xp5kklt6_1NIFjZnebgaVe7sO7s3bPi9Q,1846
|
|
6
|
+
colopresso-12.2.0.dist-info/METADATA,sha256=JU5lzk2m5hRFW7lVzHFAtS8DvYzPQz3XRM0ENEw7PzQ,18258
|
|
7
|
+
colopresso-12.2.0.dist-info/WHEEL,sha256=19Ju5BAHKq82Vugt8O3khppLt7ETVxeZiy005rNapw0,105
|
|
8
|
+
colopresso-12.2.0.dist-info/RECORD,,
|