{"id":16799995,"url":"https://github.com/nfrasser/pyoxipng","last_synced_at":"2025-03-22T02:30:55.857Z","repository":{"id":43270987,"uuid":"434056377","full_name":"nfrasser/pyoxipng","owner":"nfrasser","description":"Python wrapper for multithreaded PNG optimizer oxipng (https://github.com/shssoichiro/oxipng)","archived":false,"fork":false,"pushed_at":"2024-12-30T02:28:15.000Z","size":404,"stargazers_count":18,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T11:51:55.705Z","etag":null,"topics":["compression","image-optimization","optimization","python","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nfrasser.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-02T02:31:11.000Z","updated_at":"2025-02-09T04:57:20.000Z","dependencies_parsed_at":"2023-02-02T20:31:49.426Z","dependency_job_id":"43d1d79d-7c16-482d-ac54-b379c21e1134","html_url":"https://github.com/nfrasser/pyoxipng","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfrasser%2Fpyoxipng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfrasser%2Fpyoxipng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfrasser%2Fpyoxipng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfrasser%2Fpyoxipng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nfrasser","download_url":"https://codeload.github.com/nfrasser/pyoxipng/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244173517,"owners_count":20410298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compression","image-optimization","optimization","python","rust"],"created_at":"2024-10-13T09:30:23.870Z","updated_at":"2025-03-22T02:30:55.850Z","avatar_url":"https://github.com/nfrasser.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyoxipng\n\n[![CI](https://github.com/nfrasser/pyoxipng/actions/workflows/CI.yml/badge.svg)](https://github.com/nfrasser/pyoxipng/actions/workflows/CI.yml)\n[![PyPI](https://badgen.net/pypi/v/pyoxipng)](https://pypi.org/project/pyoxipng/)\n\nPython wrapper for multithreaded .png image file optimizer\n[oxipng](https://github.com/shssoichiro/oxipng) (written in Rust). Use\n`pyoxipng` to reduce the file size of your PNG images.\n\nJump to a section\n\n- [Installation](#installation)\n- [API](#api)\n\n  - [optimize](#oxipngoptimizeinput-outputnone-kwargs)\n  - [optimize_from_memory](#oxipngoptimize_from_memorydata-kwargs)\n  - [RawImage](#oxipngrawimage)\n\n- [Options](#options)\n  - [filter](#filter)\n  - [interlace](#interlace)\n  - [strip](#strip)\n  - [deflate](#deflate)\n- [Development](#development)\n- [License](#license)\n\n## Installation\n\nInstall from PyPI:\n\n```sh\npip install pyoxipng\n```\n\nImport in your Python code:\n\n```py\nimport oxipng\n```\n\n## API\n\n### oxipng.optimize(input, output=None, \\*\\*kwargs)\n\nOptimize a file on disk.\n\n**Parameters**:\n\n- **input** _(str | bytes | PathLike)_ – path to input file to optimize\n- **output** _(str | bytes | PathLike, optional)_ – path to optimized output result file. If not specified, overwrites input. Defaults to None\n- **\\*\\*kwargs** – [Options](#options)\n\n**Returns**\n\n- None\n\n**Raises**\n\n- **oxipng.PngError** – optimization could not be completed\n\n**Examples:**\n\nOptimize a file on disk and overwrite\n\n```py\noxipng.optimize(\"/path/to/image.png\")\n```\n\nOptimize a file and save to a new location:\n\n```py\noxipng.optimize(\"/path/to/image.png\", \"/path/to/image-optimized.png\")\n```\n\n### oxipng.optimize_from_memory(data, \\*\\*kwargs)\n\nOptimize raw data from a PNG file loaded in Python as a `bytes` object:\n\n**Parameters**:\n\n- **data** _(bytes)_ – raw PNG data to optimize\n- **\\*\\*kwargs** – [Options](#options)\n\n**Returns**\n\n- _(bytes)_ – optimized raw PNG data\n\n**Raises**\n\n- **oxipng.PngError** – optimization could not be completed\n\n**Examples:**\n\n```py\ndata = ...  # bytes of png data\noptimized_data = oxipng.optimize_from_memory(data)\nwith open(\"/path/to/image-optimized.png\", \"wb\") as f:\n    f.write(optimized_data)\n```\n\n### oxipng.RawImage\n\nCreate an optimized PNG file from raw image data:\n\n```python\nraw = oxipng.RawImage(data, width, height)\noptimized_data = raw.create_optimized_png()\n```\n\nBy 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:\n\n| Method                                                       | Description                                                                                                                            |\n| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |\n| `oxipng.ColorType.grayscale(int \\| None)`                    | Grayscale, with one color channel. Specify optional shade of gray that should be rendered as transparent.                              |\n| `oxipng.ColorType.rgb(tuple[int, int, int])`                 | RGB, with three color channels. Specify optional color value that should be rendered as transparent.                                   |\n| `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. |\n| `oxipng.ColorType.grayscale_alpha()`                         | Grayscale + Alpha, with two color channels.                                                                                            |\n| `oxipng.ColorType.rgba()`                                    | RGBA, with four color channels.                                                                                                        |\n\n**Parameters:**\n\n- **data** _(bytes | bytearray)_ – Raw image data bytes. Format depends on `color_type` and `bit_depth` parameters\n- **width** _(int)_ – Width of raw image, in pixels\n- **height** _(int)_ – Height of raw image, in pixels\n- **color_type** _([oxipng.ColorType, optional)_ – Descriptor for color type used to represent this image. Optional, defaults to `oxipng.ColorType.rgba()`\n- **bit_depth** _(int, optional)_ – Bit depth of raw image. Optional, defaults to 8\n\n**Examples:**\n\nSave RGB image data from a JPEG file, interpreting black pixels as transparent.\n\n```python\nfrom PIL import Image\nimport numpy as np\n\n# Load an image file with Pillow\njpg = Image.open(\"/path/to/image.jpg\")\n\n# Convert to RGB numpy array\nrgb_array = np.array(jpg.convert(\"RGB\"), dtype=np.uint8)\nheight, width, channels = rgb_array.shape\n\n# Create raw image with sRGB color profile\ndata = rgb_array.tobytes()\ncolor_type = oxipng.ColorType.rgb((0, 0, 0))  # black is transparent\nraw = oxipng.RawImage(data, width, height, color_type=color_type)\nraw.add_png_chunk(b\"sRGB\", b\"\\0\")\n\n# Optimize and save\noptimized = raw.create_optimized_png(level=6)\nwith open(\"/path/to/image/optimized.png\", \"wb\") as f:\n    f.write(optimized)\n```\n\nSave with data where bytes reference a color palette\n\n```python\ndata = b\"\\0\\1\\2...\"  # get index data\npalette = [[0, 0, 0, 255], [1, 23, 234, 255], ...]\ncolor_type = oxipng.ColorType.indexed(palette)\nraw = oxipng.RawImage(data, 100, 100, color_type=color_type)\noptimized = raw.create_optimized_png()\n```\n\n**Methods:**\n\n#### add_png_chunk(name, data)\n\nAdd a png chunk, such as `b\"iTXt\"`, to be included in the output\n\n**Parameters:**\n\n- **name** _(bytes)_ – PNG chunk identifier\n- **data** _(bytes | bytarray)_\n\n**Returns:**\n\n- None\n\n#### add_icc_profile(data)\n\nAdd an ICC profile for the image\n\n**Parameters:**\n\n- **data** _(bytes)_ – ICC profile data\n\n**Returns:**\n\n- None\n\n#### create_optimized_png(\\*\\*kwargs)\n\nCreate an optimized png from the raw image data using the options provided\n\n**Parameters:**\n\n- **\\*\\*kwargs** – [Options](#options)\n\n**Returns:**\n\n- _(bytes)_ optimized PNG image data\n\n## Options\n\n`optimize` , `optimize_from_memory` and `RawImage.create_optimized_png` accept the following options as keyword arguments.\n\n**Example:**\n\n```py\noxipng.optimize(\"/path/to/image.png\", level=6, fix_errors=True, interlace=oxipng.Interlacing.Adam7)\n```\n\n| Option                 | Description                                                                                                                       | Type                              | Default                   |\n| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------------------- |\n| `level`                | Set the optimization level to an integer between 0 and 6 (inclusive)                                                              | int                               | `2`                       |\n| `fix_errors`           | Attempt to fix errors when decoding the input file rather than throwing `PngError`                                                | bool                              | `False`                   |\n| `force`                | Write to output even if there was no improvement in compression                                                                   | bool                              | `False`                   |\n| `filter`               | Which filters to try on the file. Use Use enum values from `oxipng.RowFilter`                                                     | Sequence[[RowFilter](#filter)]    | `[RowFilter.NoOp]`        |\n| `interlace`            | Whether to change the interlacing type of the file. `None` will not change current interlacing type                               | [Interlacing](#interlace) \\| None | `None`                    |\n| `optimize_alpha`       | Whether to allow transparent pixels to be altered to improve compression                                                          | bool                              | `False`                   |\n| `bit_depth_reduction`  | Whether to attempt bit depth reduction                                                                                            | bool                              | `True`                    |\n| `color_type_reduction` | Whether to attempt color type reduction                                                                                           | bool                              | `True`                    |\n| `palette_reduction`    | Whether to attempt palette reduction                                                                                              | bool                              | `True`                    |\n| `grayscale_reduction`  | Whether to attempt grayscale reduction                                                                                            | bool                              | `True`                    |\n| `idat_recoding`        | If any type of reduction is performed, IDAT recoding will be performed regardless of this setting                                 | bool                              | `True`                    |\n| `scale_16`             | Whether to forcibly reduce 16-bit to 8-bit by scaling                                                                             | bool                              | `False`                   |\n| `strip`                | Which headers to strip from the PNG file, if any. Specify with `oxipng.StripChunks`                                               | [StripChunks](#strip)             | `StripChunks.none()`      |\n| `deflate`              | Which DEFLATE algorithm to use. Specify with `oxipng.Deflaters`                                                                   | [Deflaters](#deflate)             | `Deflaters.libdeflater()` |\n| `fast_evaluation`      | Whether to use fast evaluation to pick the best filter                                                                            | bool                              | `False`                   |\n| `timeout`              | Maximum amount of time to spend (in seconds) on optimizations. Further potential optimizations skipped if the timeout is exceeded | float \\| None                     | `None`                    |\n\n### filter\n\nInitialize a `filter` list or tuple with any of the following `oxipng.RowFilter` enum options:\n\n- `oxipng.RowFilter.NoOp`\n- `oxipng.RowFilter.Sub`\n- `oxipng.RowFilter.Up`\n- `oxipng.RowFilter.Average`\n- `oxipng.RowFilter.Paeth`\n- `oxipng.RowFilter.Bigrams`\n- `oxipng.RowFilter.BigEnt`\n- `oxipng.RowFilter.Brute`\n\n### interlace\n\nSet `interlace` to `None` to keep existing interlacing or to one of following `oxipng.Interlacing` enum options:\n\n- `oxipng.Interlacing.Off` (interlace disabled)\n- `oxipng.Interlacing.Adam7` (interlace enabled)\n\n### strip\n\nInitialize the `strip` option with one of the following static methods in the\n`oxipng.StripChunks` class.\n\n| Method                                      | Description                                                                                 |\n| ------------------------------------------- | ------------------------------------------------------------------------------------------- |\n| `oxipng.StripChunks.none()`                 | None                                                                                        |\n| `oxipng.StripChunks.strip(Sequence[bytes])` | Strip chunks specified in the given list                                                    |\n| `oxipng.StripChunks.safe()`                 | Strip chunks that won't affect rendering (all but cICP, iCCP, sRGB, pHYs, acTL, fcTL, fdAT) |\n| `oxipng.StripChunks.keep(Sequence[bytes])`  | Strip all non-critical chunks except those in the given list                                |\n| `oxipng.StripChunks.all()`                  | Strip all non-critical chunks                                                               |\n\n### deflate\n\nInitialize the `deflate` option with one of the following static methods in the\n`oxipng.Deflaters` class.\n\n| Method                              | Description                                                |\n| ----------------------------------- | ---------------------------------------------------------- |\n| `oxipng.Deflaters.libdeflater(int)` | Libdeflater with compression level [0-12]                  |\n| `oxipng.Deflaters.zopfli(int)`      | Zopfli with number of compression iterations to do [1-255] |\n\n## Development\n\n1. Install [Rust](https://www.rust-lang.org/tools/install)\n1. Install [Python 3.8+](https://www.python.org/downloads/)\n1. Install [Pipenv](https://pipenv.pypa.io/en/latest/)\n1. Clone this repository and navigate to it via command line\n   ```sh\n   git clone https://github.com/nfrasser/pyoxipng.git\n   cd pyoxipng\n   ```\n1. Install dependencies\n   ```sh\n   pipenv install --dev\n   ```\n1. Activate the dev environment\n   ```\n   pipenv shell\n   ```\n1. Build\n   ```sh\n   maturin develop\n   ```\n1. Run tests\n   ```\n   pytest\n   ```\n1. Format code\n   ```\n   ruff check .\n   ruff format .\n   ```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfrasser%2Fpyoxipng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnfrasser%2Fpyoxipng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfrasser%2Fpyoxipng/lists"}