<h3 align="center">AEPi</h3>
<p align="center">
Abyss Engine Image (AEI) conversion for python<br>
Join <a href='https://discord.gg/Qv8zTur'>The Kaamo Club discord server</a> for Galaxy on Fire fans and modding
</p>
</div>
<p align="center">
<a href="https://github.com/Trimatix/AEPi/actions"
><img
src="https://img.shields.io/github/actions/workflow/status/Trimatix/AEPi/testing.yml?branch=main"
alt="GitHub Actions workflow status"
/></a>
<a href="https://github.com/Trimatix/AEPi/projects/1?card_filter_query=label%3Abug"
><img
src="https://img.shields.io/github/issues-search?color=eb4034&label=bug%20reports&query=repo%3ATrimatix%2FAEPi%20is%3Aopen%20label%3Abug"
alt="GitHub open bug reports"
/></a>
<a href="https://github.com/Trimatix/AEPi/actions"
><img
src="https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/Trimatix/8a5430ecc0f87b003367174b1521f3bb/raw/AEPi__heads_main.json"
alt="Test coverage"
/></a>
</p>
<p align="center">
<a href="https://pypi.org/project/AEPi"
><img
src='https://badgen.net/pypi/v/AEPi/'
alt="Pypi package version"
/></a>
<a href="https://pypi.org/project/AEPi"
><img
src="https://img.shields.io/pypi/pyversions/AEPi.svg"
alt="Minimum supported Python version"
/></a>
<a href="https://github.com/Trimatix/AEPi/blob/master/LICENSE"
><img
src="https://img.shields.io/github/license/Trimatix/AEPi.svg"
alt="License"
</p>
<p align="center">
<a href="https://sonarcloud.io/dashboard?id=Trimatix_AEPi"
><img
src="https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=bugs"
alt="SonarCloud bugs analysis"
/></a>
<a href="https://sonarcloud.io/dashboard?id=Trimatix_AEPi"
><img
src="https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=code_smells"
alt="SonarCloud code smells analysis"
/></a>
<a href="https://sonarcloud.io/dashboard?id=Trimatix_AEPi"
><img
src="https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=alert_status"
alt="SonarCloud quality gate status"
/></a>
</p>
<!-- TABLE OF CONTENTS -->
<details open>
<summary>Table of Contents</summary>
<ol>
<li>
<a href="#about-the-project">About The Project</a>
</li>
<li>
<a href="#getting-started">Getting Started</a>
<ul>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#installation">Installation</a></li>
</ul>
</li>
<li>
<a href="#usage">Usage</a></li>
<ul>
<li><a href="#open-an-aei-file-on-disk">Open an .aei file on disk</a></li>
<li><a href="#create-a-new-aei">Create a new AEI</a></li>
</ul>
<li><a href="#roadmap">Roadmap</a></li>
<li><a href="#contributing">Contributing</a></li>
</ol>
</details>
<!-- ABOUT THE PROJECT -->
## About The Project
**Abyss Engine** is an internal-only game engine developed by Deep Silver FishLabs, for the development of the Galaxy on Fire game series.
The engine uses a proprietary file format for grids of images, called Abyss Engine Image (AEI). The image compression is platform dependant, for example Android texture files are compressed with [Ericsson Texture Compression (ETC)](https://github.com/Ericsson/ETCPACK).
The AEI format was analysed by the Russian modding group 'CatLabs', who later created a GUI and command-line tool for conversion between PNG and AEI, named AEIEditor.
This tool was closed-source, and relied on a windows DLL for compression. AEPi is a minimal recreation of the image conversion logic provided by AEIEditor, leaning on open source image codecs:
- [K0lb3/etcpak](https://github.com/K0lb3/etcpak)
- [K0lb3/tex2img](https://github.com/K0lb3/tex2img)
See <a href="#roadmap">the project roadmap</a> for currently supported and upcoming features.
<!-- GETTING STARTED -->
## Getting Started
### Prerequisites
* python 3.6+
### Installation
install AEPi from PyPi:
```
python -m pip install aepi
```
<!-- USAGE EXAMPLES -->
### Usage
This library reflects the real representation of an AEI file on disk; though textures are added to and read from an AEI object as individual images, the underlying representation is a single image. This improves encoding/decoding performance, and enables overlapping textures.
For maximum flexibility, AEPi returns AEIs as BytesIO objects.
The recommended best practise is to wrap your AEPi call in a `with` statement, to ensure that all of the AEI's images are cleaned out of memory when it goes out of scope.
#### Open an .aei file on disk
```py
from AEPi import AEI
with AEI.read("path/to/file.aei") as aei:
print(
f"The AEI is compressed in {aei.format.name} format, "
f"with {len(aei.textures)} textures. "
f"Width: {aei.shape[0]} Height: {aei.shape[0]}"
)
```
##### Reading textures as image segments
`AEI.textures` provides read access to all of the AEI's bounding boxes. The `AEI.getTexture` method returns the relevant segment of the AEI, as a Pillow `Image`.
Using this, you could for example, batch export all of the individual images within an AEI:
```py
for i, tex in enumerate(aei.textures):
with aei.getTexture(tex) as im:
im.save(f"batch/export/{i}.png")
```
#### Create a new AEI
```py
from AEPi import AEI, CompressionFormat,
from PIL import Image
image_path = "ship-texture.png"
image2_path = "another-texture.png"
# create a new .aei file
with Image.open(image_path) as image, Image.open(image2_path) as image2:
# Images are always assumed to be RGB(A). AEPi handles channel swapping for ETC1 to BGR(A)
with AEI(image) as new_aei:
# 'textures' - image bounding boxes
new_aei.addTexture(image2, 0, 0)
# The below operation is legal, but would leave unused image content in the AEI!
new_aei.removeTexture(0, 0, image2.width, image2.height, clearImage=False)
```
#### Write a new AEI file to disk
```py
with open("path/to/newFile.aei", "wb") as new_file:
# compression format can be specified at write time, or in the constructor
aei.write(new_file, format=CompressionFormat.DXT5)
```
<!-- ROADMAP -->
## Roadmap
The AEPi 1.0 release will mark feature parity with AEIEditor, which theoretically reflects all of the capabilities required to manipulate Galaxy on Fire 2 AEIs on all platforms.
For details of the work that needs to be done, see the issues listed under the 1.0 milestone: https://github.com/Trimatix/AEPi/milestones
Other work is needed (e.g documentation, QOL improvements...), but below is an overview of the *features* implementation progress towards AEIEditor parity:
|Feature |Read support|Write support |
|---------------------------|:----------:|:------------:|
|Raw image content | ✅ | ✅ |
|Basic metadata | ✅ | ✅ |
|Texture regions | ✅ | ✅ |
|Mipmapping | ✅ | ❌ |
|Compression quality (l/m/h)| ❌ | ❌ |
|Symbol maps | ❌ | ❌ |
And compression format support progress:
|Format |Read support|Write support |
|-----------------------|:----------:|:------------:|
|Uncompressed | ❌ | ❌ |
|Uncompressed_UI | ✅ | ✅ |
|Uncompressed_CubeMap_PC| ✅ | ✅ |
|Uncompressed_CubeMap | ✅ | ✅ |
|PVRTC12A | ❌ | ❌ |
|PVRTC14A | ❌ | ❌ |
|ATC | ✅ | ❌ |
|DXT1 | ✅ | ❌ |
|DXT3 | ❌ | ❌ |
|DXT5 | ✅ | ✅ |
|ETC1 | ✅ | ✅ |
Extra feature requests for after the 1.0 release are very welcome.
To report a bug or request a feature, please submit an issue to the [open issues](https://github.com/Trimatix/AEPi/issues) page of this repository.
<!-- CONTRIBUTING -->
## Contributing
This project has a huge amount of potential to help the community and extend the lifetime of our beloved game series. Your contributions will make that possible, and so I thank you deeply for your help with this project.
Please star the repository to let me know that my work is appreciated!
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
Raw data
{
"_id": null,
"home_page": "https://github.com/Trimatix/AEPi",
"name": "AEPi",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "game, python, galaxy-on-fire, image-compression, image-conversion, game-mod-tool, abyss-engine",
"author": "Jasper Law",
"author_email": "trimatix.music@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/4b/7d/f6ac32f8e4212eb53d015f99b9e57f7c3e2bb8645ce7b4594c2422790a1b/aepi-0.8.3.1.tar.gz",
"platform": null,
"description": "<h3 align=\"center\">AEPi</h3>\n <p align=\"center\">\n Abyss Engine Image (AEI) conversion for python<br>\n Join <a href='https://discord.gg/Qv8zTur'>The Kaamo Club discord server</a> for Galaxy on Fire fans and modding\n </p>\n</div>\n<p align=\"center\">\n <a href=\"https://github.com/Trimatix/AEPi/actions\"\n ><img\n src=\"https://img.shields.io/github/actions/workflow/status/Trimatix/AEPi/testing.yml?branch=main\"\n alt=\"GitHub Actions workflow status\"\n /></a>\n <a href=\"https://github.com/Trimatix/AEPi/projects/1?card_filter_query=label%3Abug\"\n ><img\n src=\"https://img.shields.io/github/issues-search?color=eb4034&label=bug%20reports&query=repo%3ATrimatix%2FAEPi%20is%3Aopen%20label%3Abug\"\n alt=\"GitHub open bug reports\"\n /></a>\n <a href=\"https://github.com/Trimatix/AEPi/actions\"\n ><img\n src=\"https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/Trimatix/8a5430ecc0f87b003367174b1521f3bb/raw/AEPi__heads_main.json\"\n alt=\"Test coverage\"\n /></a>\n</p>\n<p align=\"center\">\n <a href=\"https://pypi.org/project/AEPi\"\n ><img\n src='https://badgen.net/pypi/v/AEPi/'\n alt=\"Pypi package version\"\n /></a>\n <a href=\"https://pypi.org/project/AEPi\"\n ><img\n src=\"https://img.shields.io/pypi/pyversions/AEPi.svg\"\n alt=\"Minimum supported Python version\"\n /></a>\n <a href=\"https://github.com/Trimatix/AEPi/blob/master/LICENSE\"\n ><img\n src=\"https://img.shields.io/github/license/Trimatix/AEPi.svg\"\n alt=\"License\"\n</p>\n<p align=\"center\">\n <a href=\"https://sonarcloud.io/dashboard?id=Trimatix_AEPi\"\n ><img\n src=\"https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=bugs\"\n alt=\"SonarCloud bugs analysis\"\n /></a>\n <a href=\"https://sonarcloud.io/dashboard?id=Trimatix_AEPi\"\n ><img\n src=\"https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=code_smells\"\n alt=\"SonarCloud code smells analysis\"\n /></a>\n <a href=\"https://sonarcloud.io/dashboard?id=Trimatix_AEPi\"\n ><img\n src=\"https://sonarcloud.io/api/project_badges/measure?project=Trimatix_AEPi&metric=alert_status\"\n alt=\"SonarCloud quality gate status\"\n /></a>\n</p>\n\n\n\n<!-- TABLE OF CONTENTS -->\n<details open>\n <summary>Table of Contents</summary>\n <ol>\n <li>\n <a href=\"#about-the-project\">About The Project</a>\n </li>\n <li>\n <a href=\"#getting-started\">Getting Started</a>\n <ul>\n <li><a href=\"#prerequisites\">Prerequisites</a></li>\n <li><a href=\"#installation\">Installation</a></li>\n </ul>\n </li>\n <li>\n <a href=\"#usage\">Usage</a></li>\n <ul>\n <li><a href=\"#open-an-aei-file-on-disk\">Open an .aei file on disk</a></li>\n <li><a href=\"#create-a-new-aei\">Create a new AEI</a></li>\n </ul>\n <li><a href=\"#roadmap\">Roadmap</a></li>\n <li><a href=\"#contributing\">Contributing</a></li>\n </ol>\n</details>\n\n\n\n<!-- ABOUT THE PROJECT -->\n## About The Project\n\n**Abyss Engine** is an internal-only game engine developed by Deep Silver FishLabs, for the development of the Galaxy on Fire game series.\n\nThe engine uses a proprietary file format for grids of images, called Abyss Engine Image (AEI). The image compression is platform dependant, for example Android texture files are compressed with [Ericsson Texture Compression (ETC)](https://github.com/Ericsson/ETCPACK).\n\nThe AEI format was analysed by the Russian modding group 'CatLabs', who later created a GUI and command-line tool for conversion between PNG and AEI, named AEIEditor.\n\nThis tool was closed-source, and relied on a windows DLL for compression. AEPi is a minimal recreation of the image conversion logic provided by AEIEditor, leaning on open source image codecs:\n- [K0lb3/etcpak](https://github.com/K0lb3/etcpak)\n- [K0lb3/tex2img](https://github.com/K0lb3/tex2img)\n\nSee <a href=\"#roadmap\">the project roadmap</a> for currently supported and upcoming features.\n\n\n<!-- GETTING STARTED -->\n## Getting Started\n### Prerequisites\n\n* python 3.6+\n\n### Installation\n\ninstall AEPi from PyPi:\n```\npython -m pip install aepi\n```\n\n<!-- USAGE EXAMPLES -->\n### Usage\n\nThis library reflects the real representation of an AEI file on disk; though textures are added to and read from an AEI object as individual images, the underlying representation is a single image. This improves encoding/decoding performance, and enables overlapping textures.\n\nFor maximum flexibility, AEPi returns AEIs as BytesIO objects.\n\nThe recommended best practise is to wrap your AEPi call in a `with` statement, to ensure that all of the AEI's images are cleaned out of memory when it goes out of scope.\n\n#### Open an .aei file on disk\n\n```py\nfrom AEPi import AEI\n\nwith AEI.read(\"path/to/file.aei\") as aei:\n print(\n f\"The AEI is compressed in {aei.format.name} format, \"\n f\"with {len(aei.textures)} textures. \"\n f\"Width: {aei.shape[0]} Height: {aei.shape[0]}\"\n)\n```\n\n##### Reading textures as image segments\n\n`AEI.textures` provides read access to all of the AEI's bounding boxes. The `AEI.getTexture` method returns the relevant segment of the AEI, as a Pillow `Image`.\n\nUsing this, you could for example, batch export all of the individual images within an AEI:\n\n```py\nfor i, tex in enumerate(aei.textures):\n with aei.getTexture(tex) as im:\n im.save(f\"batch/export/{i}.png\")\n```\n\n#### Create a new AEI\n\n```py\nfrom AEPi import AEI, CompressionFormat,\nfrom PIL import Image\n\nimage_path = \"ship-texture.png\"\nimage2_path = \"another-texture.png\"\n\n# create a new .aei file\nwith Image.open(image_path) as image, Image.open(image2_path) as image2:\n # Images are always assumed to be RGB(A). AEPi handles channel swapping for ETC1 to BGR(A)\n with AEI(image) as new_aei:\n # 'textures' - image bounding boxes\n new_aei.addTexture(image2, 0, 0)\n # The below operation is legal, but would leave unused image content in the AEI!\n new_aei.removeTexture(0, 0, image2.width, image2.height, clearImage=False)\n```\n\n#### Write a new AEI file to disk\n\n```py\n with open(\"path/to/newFile.aei\", \"wb\") as new_file:\n # compression format can be specified at write time, or in the constructor\n aei.write(new_file, format=CompressionFormat.DXT5)\n```\n\n<!-- ROADMAP -->\n## Roadmap\n\nThe AEPi 1.0 release will mark feature parity with AEIEditor, which theoretically reflects all of the capabilities required to manipulate Galaxy on Fire 2 AEIs on all platforms.\n\nFor details of the work that needs to be done, see the issues listed under the 1.0 milestone: https://github.com/Trimatix/AEPi/milestones\n\nOther work is needed (e.g documentation, QOL improvements...), but below is an overview of the *features* implementation progress towards AEIEditor parity:\n\n|Feature |Read support|Write support |\n|---------------------------|:----------:|:------------:|\n|Raw image content | \u2705 | \u2705 |\n|Basic metadata | \u2705 | \u2705 |\n|Texture regions | \u2705 | \u2705 |\n|Mipmapping | \u2705 | \u274c |\n|Compression quality (l/m/h)| \u274c | \u274c |\n|Symbol maps | \u274c | \u274c |\n\nAnd compression format support progress:\n\n|Format |Read support|Write support |\n|-----------------------|:----------:|:------------:|\n|Uncompressed | \u274c | \u274c |\n|Uncompressed_UI | \u2705 | \u2705 |\n|Uncompressed_CubeMap_PC| \u2705 | \u2705 |\n|Uncompressed_CubeMap | \u2705 | \u2705 |\n|PVRTC12A | \u274c | \u274c |\n|PVRTC14A | \u274c | \u274c |\n|ATC | \u2705 | \u274c |\n|DXT1 | \u2705 | \u274c |\n|DXT3 | \u274c | \u274c |\n|DXT5 | \u2705 | \u2705 |\n|ETC1 | \u2705 | \u2705 |\n\nExtra feature requests for after the 1.0 release are very welcome.\n\nTo report a bug or request a feature, please submit an issue to the [open issues](https://github.com/Trimatix/AEPi/issues) page of this repository.\n\n\n<!-- CONTRIBUTING -->\n## Contributing\n\nThis project has a huge amount of potential to help the community and extend the lifetime of our beloved game series. Your contributions will make that possible, and so I thank you deeply for your help with this project.\n\nPlease star the repository to let me know that my work is appreciated!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n",
"bugtrack_url": null,
"license": null,
"summary": "Read and write Abyss Engine Image (AEI) files from python, for Galaxy on Fire 2",
"version": "0.8.3.1",
"project_urls": {
"Bug Tracker": "https://github.com/Trimatix/AEPi/issues",
"Homepage": "https://github.com/Trimatix/AEPi"
},
"split_keywords": [
"game",
" python",
" galaxy-on-fire",
" image-compression",
" image-conversion",
" game-mod-tool",
" abyss-engine"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "98a7bb08128abfab5de489f889a3dec6aa6f1f514802da23b2d4a84a9e4fb5dc",
"md5": "8d940e841e7ef53b1ac05abbed611daa",
"sha256": "1c8a63646657ea88bbbff076dd64d62ad9f38fcf9da16ffd8482b0d50fe1e099"
},
"downloads": -1,
"filename": "AEPi-0.8.3.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8d940e841e7ef53b1ac05abbed611daa",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 21879,
"upload_time": "2024-05-08T21:58:29",
"upload_time_iso_8601": "2024-05-08T21:58:29.534366Z",
"url": "https://files.pythonhosted.org/packages/98/a7/bb08128abfab5de489f889a3dec6aa6f1f514802da23b2d4a84a9e4fb5dc/AEPi-0.8.3.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4b7df6ac32f8e4212eb53d015f99b9e57f7c3e2bb8645ce7b4594c2422790a1b",
"md5": "0e8a2ec0309983ce61e026b48fbe228f",
"sha256": "dd71cdc8ec60aec683dbab84b19622950c0d782b21615b1cfb0151e02fe5bb4b"
},
"downloads": -1,
"filename": "aepi-0.8.3.1.tar.gz",
"has_sig": false,
"md5_digest": "0e8a2ec0309983ce61e026b48fbe228f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 21967,
"upload_time": "2024-05-08T21:58:30",
"upload_time_iso_8601": "2024-05-08T21:58:30.620038Z",
"url": "https://files.pythonhosted.org/packages/4b/7d/f6ac32f8e4212eb53d015f99b9e57f7c3e2bb8645ce7b4594c2422790a1b/aepi-0.8.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-08 21:58:30",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Trimatix",
"github_project": "AEPi",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [
{
"name": "pillow",
"specs": []
},
{
"name": "tex2img",
"specs": []
},
{
"name": "etcpak",
"specs": []
}
],
"lcname": "aepi"
}