97 Commits
0.0.4 ... main

Author SHA1 Message Date
a05c1e352e Release 0.2.1
### Fixed

- Fixed broken transparency on palettized PNG files

### Changed

- Changed which wheels are built by the CI. There are no changes to OS or Python version compatibility if you compile from source.
	- Stopped building Python 3.7 wheels
	- Stopped building macOS universal wheels
	- Wheels for macOS now require macOS 12 or later
	- Included macOS ARM wheels 
	- Included Python 3.12 wheels
2024-06-02 18:58:48 -07:00
1f7aad7218 skip python3.7 because its EOL
Still supported for now, just no wheels provided
2024-06-02 17:56:13 -07:00
23133eb802 Fix build matrix and macOS target 2024-06-02 17:43:33 -07:00
0448dbe6e1 Update CIBuildWheel 2024-06-02 17:32:00 -07:00
ec7953dcff Release 0.2.0
### Changed

- Updated Pybind11 to version 3.10, adding Python 3.11 support
- Updated install instructions in readme to reflect availability on PyPI
- Encode now skips .dds files in its input to prevent needless re-encoding

### Added

- Added the `-n` option for bc3 encoding to perform a BC3nm swizzle
2023-06-21 15:46:13 -07:00
3280fc74be Merge branch 'dev' 2023-06-21 15:45:35 -07:00
cbec93ed55 Skip any dds files when encoding 2023-06-21 15:41:08 -07:00
8509384bff Add -n option to encode bc3 which performs a BC3nm swizzle 2023-06-21 15:32:24 -07:00
1c86b09ca0 Fix docs link 2023-06-21 15:31:47 -07:00
d4eada16f9 Update readme with easier install directions 2023-06-21 15:11:17 -07:00
aed575edc6 Release 0.1.4
### Changed

- Updated Pybind11 to version 3.10, adding Python 3.11 support
2022-10-29 23:32:05 -07:00
4cdcb65f3a Merge branch 'dev' 2022-10-29 23:31:45 -07:00
0a66fcca20 Merge pull request #35 from drewcassidy/dependabot/github_actions/dev/pypa/cibuildwheel-2.11.2
Bump pypa/cibuildwheel from 2.5.0 to 2.11.2
2022-10-29 22:13:20 -07:00
37f0673e95 Merge pull request #33 from drewcassidy/dependabot/github_actions/dev/actions/setup-python-4.3.0
Bump actions/setup-python from 4.0.0 to 4.3.0
2022-10-29 22:12:59 -07:00
b81df96990 track python dependencies 2022-10-29 21:55:53 -07:00
38beffef05 Bump pypa/cibuildwheel from 2.5.0 to 2.11.2
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.5.0 to 2.11.2.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/2.5.0...v2.11.2)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-29 21:05:59 -07:00
0dccd1cd07 Update pybind to 3.10 to allow Python 3.11 support 2022-10-29 21:03:12 -07:00
7ea104f712 Bump actions/setup-python from 4.0.0 to 4.3.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.0.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4.0.0...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 12:46:28 +00:00
9cb60f0ce2 Merge pull request #21 from drewcassidy/dependabot/github_actions/dev/actions/setup-python-4.0.0
Bump actions/setup-python from 3.1.2 to 4.0.0
2022-06-12 18:02:11 -07:00
15e0c68df6 Merge branch 'dev' into dependabot/github_actions/dev/actions/setup-python-4.0.0 2022-06-12 17:18:18 -07:00
9f54349556 Specify python versions 2022-06-12 17:16:18 -07:00
71c069d30c Bump actions/setup-python from 3.1.2 to 4.0.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3.1.2 to 4.0.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3.1.2...v4.0.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-09 11:32:38 +00:00
661536e6f6 use scoped lock 2022-05-22 20:59:37 -07:00
920059bea1 Migrate tests to pytest 2022-05-22 18:40:13 -07:00
daae86cf50 Switch to pytest 2022-05-22 16:50:24 -07:00
5c87c82702 Add file documenting development environment setup 2022-05-11 23:22:51 -07:00
ddbeff43cb Update copyright year 2022-05-11 20:51:35 -07:00
5c94782876 Remove debug wrapper, now that I know how to use a debug python build 2022-05-10 22:08:01 -07:00
9eaaf901f3 Fix compilation of test wrapper 2022-05-08 16:06:36 -07:00
c79ffc8794 Bump docker/setup-qemu-action from 1 to 2
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1 to 2.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-06 18:33:39 -07:00
55f0ced229 getting started instructions 2022-05-04 23:29:28 -07:00
eb7b259d53 Autogenerated command documentation from helpstrings 2022-05-04 23:03:06 -07:00
03801e2e1b New index page and remove broken page 2022-05-04 22:51:40 -07:00
3a28ec690c Merge remote-tracking branch 'origin/dependabot/github_actions/pypa/cibuildwheel-2.5.0' into dev 2022-05-02 22:42:11 -07:00
697f7243a0 Documentation nice-to-haves 2022-05-02 22:41:39 -07:00
22e1455ceb tell dependabot to target the dev branch 2022-05-02 22:26:05 -07:00
c13f64828f Bump pypa/cibuildwheel from 2.4.0 to 2.5.0
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v2.4.0...2.5.0)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 11:41:47 +00:00
9a57b096f5 Set min version for sphinx tools 2022-04-21 09:34:21 -07:00
82f079f1b6 Enable RTD building 2022-04-19 21:55:00 -07:00
2c72b7ad22 Ignore previous commit in blames 2022-04-18 19:56:41 -07:00
cb84f32eda Migrate code style to Black 2022-04-18 19:53:26 -07:00
b34fdf2316 Ignore wheels and sdists 2022-04-16 22:40:54 -07:00
ac4e5b2679 Release 0.1.3
### Fixed

- Fixed quicktex not compiling for python 3.10 on Windows

### Changed

- Reworked CI job, adding wheels for ARM macOS, ARM Linux, and x86 musl Linux.
- Added wheels for python 3.10
- Added a more useful error message when importing quicktex on macOS when libomp.dylib isn't installed
2022-04-12 19:21:06 -07:00
25e74b9b08 Bump actions/setup-python from 3.1.1 to 3.1.2
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3.1.1...v3.1.2)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-12 18:24:37 -07:00
a881a0a36b Add more helpful error when importing without libomp installed
Also use non-shallow clones in ci
2022-04-11 23:05:20 -07:00
3fdfc3ecaa Pretty job names 2022-04-11 21:48:22 -07:00
b440543de3 why 2022-04-11 21:18:43 -07:00
23ed54c7a2 fix conditional 2022-04-11 21:15:15 -07:00
e7e8657100 fix syntax error 2022-04-11 21:11:19 -07:00
2a07db8c8f Run arm64 linux builds on their own job for faster CI 2022-04-11 21:09:50 -07:00
b8a80235f8 Bump actions/upload-artifact from 2 to 3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 10:26:24 -07:00
4cac24798e Bump actions/download-artifact from 2 to 3
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 10:25:24 -07:00
9b6097373e Another attempt 2022-04-10 22:03:17 -07:00
b954ac6ccc Attempt to hint to cmake what python install to use correctly
Should fix my linux building issue?
2022-04-10 21:51:18 -07:00
593a0c3f46 Fix windows test command and install fat binaries for libomp 2022-04-10 21:08:07 -07:00
3b73bc8bce use Py_ssize_t to make msvc happy 2022-04-10 01:06:25 -07:00
abeb08fc81 Upgrade cibuildwheel to 2.4.0 2022-04-10 00:26:00 -07:00
77637f6abd Run tests in the right directory and skip linux for now 2022-04-10 00:22:13 -07:00
df6d5b1848 Use latest setuptools instead of pinning it 2022-04-10 00:09:44 -07:00
b5aea803d5 Use relative imports in tests 2022-04-10 00:04:08 -07:00
b80a6d2229 Fix arch selection and test command 2022-04-09 23:15:23 -07:00
dac7f07db4 Build for musl linux for platforms supported by Pillow
Specifically x64 for cpython 3.8-3.10
2022-04-09 22:54:06 -07:00
7dfefa3007 Skip musl linux wheel builds
Pillow appears to fail to compile on these without installing a bunch of dependencies, so... sorry alpine users
2022-04-09 22:40:05 -07:00
eaca455a08 syntax error 2022-04-09 22:24:35 -07:00
e5ccdbb4f4 Don't try to download test images 2022-04-09 22:23:00 -07:00
94d88c7e00 Remove nose dependence
Also move test images into the base repo because they're not very big anyways
2022-04-09 22:20:09 -07:00
9421a6d372 Merge branch 'main' into build-modernization 2022-04-09 20:39:43 -07:00
cab0eeebae Merge pull request #10 from drewcassidy/dependabot/github_actions/actions/checkout-3
Bump actions/checkout from 2 to 3
2022-04-09 20:21:43 -07:00
3d98b37a37 Merge pull request #13 from drewcassidy/dependabot/github_actions/actions/setup-python-3.1.1
Bump actions/setup-python from 2 to 3.1.1
2022-04-09 20:21:33 -07:00
654b6d628a Slightly modernize how project is compiled 2022-04-09 19:43:40 -07:00
1502c5318c Bump actions/setup-python from 2 to 3.1.1
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 3.1.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v3.1.1)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-07 11:45:36 +00:00
421876ab0f Move more metadata to pyproject.toml 2022-04-03 20:41:02 -07:00
29590e0323 Move a good chunk of metadata to pyproject.toml 2022-04-03 16:22:47 -07:00
8b4e3c5746 Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-03 20:15:09 +00:00
8e7b95609c Dependabot for gh actions 2022-04-03 13:12:29 -07:00
71379b7ae1 Revert to manylinux2014 2022-04-03 00:05:35 -07:00
d1346ca11d Enable macos cross-compiling in setup.py 2022-04-02 21:39:14 -07:00
e488dbcbff Fix builder version
and here I was thinking this was semver smh
2022-04-01 21:07:57 -07:00
1f7b45aa57 Compile for multiple architectures 2022-04-01 21:06:51 -07:00
70b7251eae Include build for python 3.10 (finally) 2022-04-01 20:27:00 -07:00
e8e0f4e29b Release 0.1.2
### Fixed

- Fixed sdist not including pybind
2022-03-27 14:29:57 -07:00
6d7f56476f Add manifest file 2022-03-27 14:28:17 -07:00
b4d2388615 Release 0.1.1
### Fixed

- Fixed alpha premultiplication when generating mipmaps
2021-09-28 20:42:13 -07:00
f7d57aa859 Fix alpha premultiplication being used when generating mipmaps 2021-09-28 20:40:01 -07:00
24b064e6b4 Version 0.1.0
### Added

- Began publishing to PyPI

### Changed

- Rewrote CI workflow to include ManyLinux2014 builds
- Reverted project to C++17 for better compiler compatibility
2021-05-09 19:46:51 -07:00
28930d89d5 update changelog 2021-05-09 19:46:05 -07:00
4f25e0f750 fix tests dir 2021-05-08 23:15:52 -07:00
433e728424 pytmon 2021-05-08 23:07:37 -07:00
4939171d5d Rework CI workflow 2021-05-08 23:06:13 -07:00
f0f132328c Dont require findpython mode 2021-05-08 19:54:16 -07:00
7a11901aa6 Fix brace expansion 2021-05-08 18:41:41 -07:00
cb8b251baf Put back matrix for os 2021-05-08 18:29:45 -07:00
463956b63b Fix environment variables..? 2021-05-08 18:22:31 -07:00
22cc5f6148 Fix environment variables 2021-05-08 18:18:14 -07:00
0478532cb9 Test using CIBW 2021-05-08 18:12:37 -07:00
f2873f3a38 Downgrade project to C++17 2021-05-08 16:50:05 -07:00
2618faadfc Fix cli module 2021-04-20 15:14:51 -07:00
104 changed files with 1112 additions and 706 deletions

8
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,8 @@
# git-blame ignored revisions
# To configure, run
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Requires Git > 2.23
# See https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt
# Migrate code style to Black
cb84f32edab717389d03a3855aa5bd4d0db1ae3c

16
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,16 @@
# Set update schedule for GitHub Actions
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "dev"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"
# Maintain dependencies for pip
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"

View File

@ -6,43 +6,25 @@ name: Python Package
on: [ push, pull_request ]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [ 3.7, 3.8, 3.9 ]
os: [ macos-latest, windows-latest, ubuntu-latest ]
build-sdist:
name: Build SDist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
# Whether to checkout submodules: `true` to checkout submodules or `recursive` to
# recursively checkout submodules.
submodules: 'true'
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
- name: Set up Python
uses: actions/setup-python@v4.3.0
with:
python-version: ${{ matrix.python-version }}
- name: Set linux compiler
if: runner.os == 'Linux'
run: |
echo "CC=gcc-10" >> $GITHUB_ENV
echo "CXX=g++-10" >> $GITHUB_ENV
- name: Install libomp
if: runner.os == 'macOS'
# openMP isnt part of core apple clang for some reason?
run: brew install libomp
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8
- name: Install test images
run: git clone https://git.pileof.rocks/drewcassidy/quicktex-test-images.git tests/images
python -m pip install setuptools twine build
- name: Lint with flake8
run: |
@ -51,95 +33,110 @@ jobs:
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Compile and install
run: python -m pip install -e .[tests]
- name: Build SDist
run: python -m build --sdist
- name: Test with nose
run: nosetests tests -d
- name: Check metadata
run: python -m twine check dist/*
build:
needs: test
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- name: Upload SDist
uses: actions/upload-artifact@v3
with:
path: dist/*.tar.gz
build-wheels:
name: Build Wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
MACOSX_DEPLOYMENT_TARGET: 10.15
strategy:
matrix:
python-version: [ 3.7, 3.8, 3.9 ]
os: [ macos-latest, windows-latest ]
# macos-13 is an intel runner, macos-14 is apple silicon
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
linux_arch: [ 'x86_64' ] #[suffix, mac, windows, linux] arch names
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
# Whether to checkout submodules: `true` to checkout submodules or `recursive` to
# recursively checkout submodules.
submodules: 'true'
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Set linux compiler
if: runner.os == 'Linux'
run: |
echo "CC=gcc-10" >> $GITHUB_ENV
echo "CXX=g++-10" >> $GITHUB_ENV
fetch-depth: 0
- name: Install libomp
if: runner.os == 'macOS'
# openMP isnt part of core apple clang for some reason?
run: brew install libomp
- name: Install dependencies
# libomp is in homebrew, which works for end users but its not a fat binary
# so we have to install it manually
# compiled dylibs courtesy of https://mac.r-project.org/openmp/ and mirrored on my own server
run: |
python -m pip install --upgrade pip
python -m pip install setuptools wheel twine build
wget https://pileof.rocks/openmp-13.0.0-darwin21-Release.tar.gz
sudo tar fvxz openmp-*.tar.gz -C /
- name: Build a binary wheel
run: python -m build --wheel --outdir dist/
- name: Upload wheel as artifact
uses: actions/upload-artifact@v2
- name: Install QEMU
# install QEMU if building for linux
uses: docker/setup-qemu-action@v2
if: runner.os == 'linux'
with:
name: dist
path: dist
platforms: arm64
- name: Build wheels
uses: pypa/cibuildwheel@v2.18.1
env:
MACOSX_DEPLOYMENT_TARGET: "12"
CIBW_ARCHS_LINUX: 'x86_64 aarch64'
CIBW_ARCHS_MACOS: 'native'
CIBW_SKIP: 'cp37*'
- name: Upload Wheels
uses: actions/upload-artifact@v3
with:
path: ./wheelhouse/*.whl
publish:
needs: build
name: Publish to PyPI and Github
needs: [ build-wheels, build-sdist ]
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
# Whether to checkout submodules: `true` to checkout submodules or `recursive` to
# recursively checkout submodules.
submodules: 'true'
- uses: actions/checkout@v3 # just need the changelog
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4.3.0
with:
python-version: '3.x'
- name: Download artifacts
uses: actions/download-artifact@v2
- name: List artifacts
run: ls -l dist
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install setuptools wheel twine build
python -m pip install yaclog
- name: Build a source tarball
run: python -m build --sdist --outdir dist/
- name: Get version name and body
run: |
echo "VERSION_TILE=Version $(yaclog show -n)" >> $GITHUB_ENV
echo "$(yaclog show -mb)" >> RELEASE.md
- name: Download Artifacts
uses: actions/download-artifact@v3
with:
name: artifact
path: dist
- name: List artifacts
run: ls -l dist
- name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
repository_url: https://test.pypi.org/legacy/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Publish to Github
uses: softprops/action-gh-release@v1
with:
files: dist/*
name: ${{ env.VERSION_TITLE }}
body_path: RELEASE.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View File

@ -5,6 +5,8 @@ build/
*.egg-info
*.pyc
*.pyi
*.whl
*.tar.gz
#sphinx
docs/_build/
@ -12,9 +14,6 @@ docs/_build/
#mypy
out
# Test images
tests/images/
# IDEs
**/.idea

4
.gitmodules vendored
View File

@ -1,4 +0,0 @@
[submodule "extern/pybind11"]
path = extern/pybind11
url = https://github.com/pybind/pybind11.git
branch = stable

28
.readthedocs.yaml Normal file
View File

@ -0,0 +1,28 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-20.04
tools:
python: "3.10"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# If using Sphinx, optionally build your docs in additional formats such as PDF
formats:
- pdf
# Give python build instructions
python:
install:
- method: pip
path: .
extra_requirements:
- docs

70
CHANGELOG.md Normal file
View File

@ -0,0 +1,70 @@
# Changelog
All notable changes to this project will be documented in this file
## 0.2.1 - 2024-06-03
### Fixed
- Fixed broken transparency on palettized PNG files
### Changed
- Changed which wheels are built by the CI. There are no changes to OS or Python version compatibility if you compile from source.
- Stopped building Python 3.7 wheels
- Stopped building macOS universal wheels
- Wheels for macOS now require macOS 12 or later
- Included macOS ARM wheels
- Included Python 3.12 wheels
## 0.2.0 - 2023-06-21
### Changed
- Updated Pybind11 to version 3.10, adding Python 3.11 support
- Updated install instructions in readme to reflect availability on PyPI
- Encode now skips .dds files in its input to prevent needless re-encoding
### Added
- Added the `-n` option for bc3 encoding to perform a BC3nm swizzle
## 0.1.3 - 2022-04-13
### Fixed
- Fixed quicktex not compiling for python 3.10 on Windows
### Changed
- Reworked CI job, adding wheels for ARM macOS, ARM Linux, and x86 musl Linux.
- Added wheels for python 3.10
- Added a more useful error message when importing quicktex on macOS when libomp.dylib isn't installed
## 0.1.2 - 2022-03-27
### Fixed
- Fixed sdist not including pybind
## 0.1.1 - 2021-09-29
### Fixed
- Fixed alpha premultiplication when generating mipmaps
## 0.1.0 - 2021-05-10
### Added
- Began publishing to PyPI
### Changed
- Rewrote CI workflow to include ManyLinux2014 builds
- Reverted project to C++17 for better compiler compatibility

View File

@ -1,13 +1,13 @@
cmake_minimum_required(VERSION 3.17)
include(CheckIPOSupported)
cmake_minimum_required(VERSION 3.18)
include(tools/CompilerWarnings.cmake)
set(CMAKE_VERBOSE_MAKEFILE ON)
project(quicktex)
# Find dependencies
find_package(Python COMPONENTS Interpreter Development REQUIRED)
find_package(Python COMPONENTS Interpreter Development.Module)
find_package(pybind11 CONFIG REQUIRED)
find_package(OpenMP)
add_subdirectory(extern/pybind11)
# Collect source files
file(GLOB SOURCE_FILES
@ -30,8 +30,6 @@ file(GLOB HEADER_FILES
"quicktex/s3tc/interpolator/*.h"
)
file(GLOB TEST_FILES "tests/*.cpp")
file(GLOB_RECURSE PYTHON_FILES "src/**/*.py")
# Organize source files together for some IDEs
@ -42,34 +40,24 @@ pybind11_add_module(_quicktex
${SOURCE_FILES}
${HEADER_FILES})
add_executable(test_quicktex
${SOURCE_FILES}
${HEADER_FILES}
${TEST_FILES})
target_link_libraries(test_quicktex PRIVATE pybind11::embed)
target_compile_definitions(test_quicktex PRIVATE -DCUSTOM_SYS_PATH="${CMAKE_HOME_DIRECTORY}/env/lib/python3.9/site-packages")
# Set Quicktex version info
target_compile_definitions(_quicktex PRIVATE VERSION_INFO=${QUICKTEX_VERSION_INFO})
# enable openMP if available
if (OpenMP_CXX_FOUND)
target_link_libraries(_quicktex PUBLIC OpenMP::OpenMP_CXX)
target_link_libraries(test_quicktex PUBLIC OpenMP::OpenMP_CXX)
endif ()
# Set module features, like C/C++ standards
target_compile_features(_quicktex PUBLIC cxx_std_20 c_std_11)
target_compile_features(test_quicktex PUBLIC cxx_std_20 c_std_11)
target_compile_features(_quicktex PUBLIC cxx_std_17 c_std_11)
# Set compiler warnings
set_project_warnings(_quicktex)
set_project_warnings(test_quicktex)
set(CMAKE_VERBOSE_MAKEFILE ON)
# Clang-specific
if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlib=libc++ -fsanitize=undefined")
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
endif ()

25
DEVELOPMENT.md Normal file
View File

@ -0,0 +1,25 @@
# Development
This document outlines how to set up a development environment for Quicktex. Documentation on writing Python extension modules is sparse, so I hope this document is useful for other projects as well. The [Coding Patterns for Python Extensions](https://pythonextensionpatterns.readthedocs.io/en/latest/) site has some useful information and will be linked to often in this document.
## Setting up Debug Python
Many development tools require debug symbols to function, and since the front-end for accessing an extension module is Python, that usually means adding debug symbols to Python. [This Page](https://pythonextensionpatterns.readthedocs.io/en/latest/debugging/debug_python.html) has some instructions on building python with debug symbols.
If you plan to use DTrace, enable the `--with-dtrace` flag when running `configure`.
It's useful for this debug python to have SSL enabled so that packages can be installed using pip. Enable SSL with the `--with-openssl` flag when running `configure`. If you are on macOS and installed OpenSSL through Homebrew, you may need to use `--with-openssl=$(brew --prefix openssl)` to help the compiler find it.
### Installing Debug Python
You can keep the resulting binary in your local copy of the cpython repo and symlink to it, but I like to install it somewhere like `/opt/python-debug/`. The install location is set in the `configure` tool using the `--prefix` flag, and installation is done by running `make install`
### Mixing Debug and Release Python
The debug build of python is slow (It may be possible to build with debug symbols but full optimization, I have not looked into it). If you already have a venv setup for your project, you can just symlink the debug python binary into `env/bin` with a full name like `python3.9d`. Make sure that the debug build has the same minor version (e.g '3.9') as the version you made the virtual environment with to maintain ABI compatibility.
## Profiling with Dtrace
DTrace is the default program profiler on macOS and other Unix systems, but it's also available for use on Windows and Linux. Using DTrace requires building Python with DTrace hooks as seen above.
Your extension module does not need a full debug build to profile, but it does need frame pointers to see the stack trace at each sample, as well as debug symbols to give functions names. The cmake build type `RelWithDebInfo` handles this automatically.

View File

@ -9,15 +9,32 @@ comparable to the original library.
## Installation
To install, first clone this repo and cd into it, then run:
### From Wheel (Easiest)
To install, run
```shell
pip install quicktex
```
If you are on macOS, You need to install openMP from homebrew:
```shell
brew install libomp
```
### From Source
To build from source, first clone this repo and cd into it, then run:
```shell
git submodule update --init
pip install .
```
and setuptools will take care of any dependencies for you.
If you are on macOS, it is recommended to first install openMP from homebrew to enable
If you are on macOS, it is recommended to first install openMP from homebrew to enable
multithreading, since it is not included in the default Apple Clang install:
```shell
@ -31,8 +48,6 @@ required dependencies for them, install with options like so:
pip install .[tests,stubs,docs]
```
Quicktex will be available on Pypi once it is out of alpha.
## Usage
```

2
docs/changelog.md Normal file
View File

@ -0,0 +1,2 @@
```{include} ../CHANGELOG.md
```

View File

@ -13,12 +13,13 @@
# import os
# import sys
# sys.path.insert(0, os.path.abspath('..'))
from datetime import date
# -- Project information -----------------------------------------------------
project = 'Quicktex'
copyright = '2021, Andrew Cassidy'
copyright = f'{date.today().year}, Andrew Cassidy'
author = 'Andrew Cassidy'
# -- General configuration ---------------------------------------------------
@ -28,11 +29,14 @@ author = 'Andrew Cassidy'
# ones.
extensions = [
'myst_parser',
'sphinx_click',
'sphinx_rtd_theme',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
]
myst_heading_anchors = 2
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -70,5 +74,5 @@ autodoc_default_options = {
# should be linked to in this documentation.
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'PIL': ('https://pillow.readthedocs.io/en/stable/', None)
'PIL': ('https://pillow.readthedocs.io/en/stable/', None),
}

2
docs/development.md Normal file
View File

@ -0,0 +1,2 @@
```{include} ../DEVELOPMENT.md
```

View File

@ -0,0 +1,7 @@
# Command Reference
```{eval-rst}
.. click:: quicktex.__main__:main
:prog: quicktex
:nested: full
```

View File

@ -0,0 +1,84 @@
# Getting Started
## Installation
Install and update using [pip](https://pip.pypa.io/en/stable/quickstart/):
```shell
pip install -U quicktex
```
If you are on macOS, you need to install openMP to allow multithreading, since it does not ship with the built-in Clang.
This can be done easily
using [homebrew](https://brew.sh). This is not required if building from source, but highly recommended.
```shell
brew install libomp
```
If you want, you can also install from source. First clone the [git repo](https://github.com/drewcassidy/quicktex) and
install it with:
```shell
pip install .
```
and setuptools will take care of any dependencies for you.
The package also makes tests, stub generation, and docs available. To install the
required dependencies for them, install with options like so:
```shell
pip install quicktex[tests,stubs,docs]
```
## Usage
For detailed documentation on the {command}`quicktex` command and its subcommands see the {doc}`commands`.
### Examples
#### Encoding a file
To encode a file in place, use the {command}`encode` command
```shell
quicktex encode auto bun.png # chooses format based on alpha
quicktex encode bc3 bun.png # encodes as bc3
```
the auto subcommand automatically chooses between bc1 and bc3 for your image depending on the contents of its alpha
channel. Quicktex supports reading from all image formats supported by [pillow](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html).
By default, Quicktex converts in place, meaning the above command will produce a `bun.dds` file alongside the png. If
you want to replace the png, use the `-r` flag to remove it after converting.
if you want to specify an output filename or directory use the `-o` flag.
```shell
quicktex encode auto -o rabbit.dds bun.png # produces rabbit.dds
quicktex.encode auto -o textures/ bun.png # produces textures/bun.dds, if textures/ exists
```
#### Encoding multiple files
quicktex is also able to convert multiple files at once, for example, to encode every png file in the images folder,
use:
```shell
quicktex encode auto images/*.png # encodes in-place
quicktex encode auto -o textures/ images/*.png # encodes to the textures/ directory
```
please note that globbing is an operation performed by your shell and is not supported by the built in windows `cmd.exe`
. If you are on Windows, please use Powershell or any posix-ish shell like [fish](https://fishshell.com).
#### Decoding files
decoding is performed exactly the same as encoding, except without having to specify a format. The output image format
is set using the `-x` flag, and defaults to png. Quicktex supports writing to all image formats supported by [pillow](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html)
```shell
quicktex decode bun.dds # produces bun.png
quicktex decode -x .tga bun2.dds # produces bun.tga
```

10
docs/handbook/index.md Normal file
View File

@ -0,0 +1,10 @@
# Handbook
```{toctree}
---
maxdepth: 3
---
commands
getting_started
```

35
docs/index.md Normal file
View File

@ -0,0 +1,35 @@
# Welcome to Quicktex's Documentation
[![Documentation Status](https://readthedocs.org/projects/quicktex/badge/?version=latest)](https://quicktex.readthedocs.io/en/latest/?badge=latest)
[![Python Package](https://github.com/drewcassidy/quicktex/actions/workflows/python-package.yml/badge.svg)](https://github.com/drewcassidy/quicktex/actions/workflows/python-package.yml)
[![PyPI version](https://badge.fury.io/py/quicktex.svg)](https://badge.fury.io/py/quicktex)
Quicktex is a Python library for encoding, decoding, and manipulating compressed textures. It uses a backend written in
C++ for superior performance, as well as an extensive API for low-level access to the texture data. The compression
engine is based in [rgbcx](https://github.com/richgel999/bc7enc).
```{toctree}
---
maxdepth: 2
caption: Contents
---
handbook/index
reference/index
```
```{toctree}
---
maxdepth: 1
---
development
Changelog <changelog>
License <license>
```
## Indices and tables
* {ref}`genindex`
* {ref}`modindex`
* {ref}`search`

View File

@ -1,15 +0,0 @@
Welcome to Quicktex's documentation!
========================================
.. toctree::
:maxdepth: 2
reference/index.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

2
docs/license.md Normal file
View File

@ -0,0 +1,2 @@
```{include} ../LICENSE.md
```

View File

@ -1,10 +0,0 @@
.. py:currentmodule:: quicktex
Conversion
============
.. autoclass:: BlockEncoder
:members:
.. autoclass:: BlockDecoder
:members:

View File

@ -1,10 +1,9 @@
Reference
=========
API Reference
=============
.. toctree::
:maxdepth: 2
conversion.rst
dds.rst
image_utils.rst
formats/index.rst

1
extern/pybind11 vendored

Submodule extern/pybind11 deleted from 8de7772cc7

View File

@ -1,11 +1,85 @@
[build-system]
requires = [
"setuptools>=42",
"setuptools>=61",
"setuptools_scm>=6.2",
"wheel",
"cmake>=3.18",
"pybind11~=2.10",
"ninja; sys_platform != 'win32'",
"cmake>=3.12",
"setuptools_scm[toml]>=3.4"
]
build-backend = "setuptools.build_meta"
[project]
name = "quicktex"
description = "A fast block compression library for python"
readme = "README.md"
authors = [{ name = "Andrew Cassidy", email = "drewcassidy@me.com" }]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: C++",
]
requires-python = ">=3.7"
dependencies = ["Pillow", "click"]
dynamic = ["version"]
[project.optional-dependencies]
tests = ["parameterized", "pytest"]
docs = [
"Sphinx >= 3.5",
"sphinx-click >= 2.7",
"sphinx-rtd-theme",
"myst-parser >= 0.14",
]
stubs = ["pybind11-stubgen"]
[project.urls]
Docs = "https://quicktex.readthedocs.io/en/latest/"
Source = "https://github.com/drewcassidy/quicktex"
Changelog = "https://github.com/drewcassidy/quicktex/blob/main/CHANGELOG.md"
[project.scripts]
quicktex = "quicktex.__main__:main"
[tool.setuptools]
zip-safe = false
packages = { find = { include = ["quicktex*"] } } # only include quicktex and not tests
package-data = { '*' = ['py.typed', '*.pyi'] } # include stubs
package-dir = { '' = '.' } # without this line, C++ source files get included in the bdist
[tool.setuptools_scm]
[tool.cibuildwheel]
build = "cp*" # only build wheels for cpython.
build-frontend = "build"
test-command = "pytest {project}/tests --verbose"
test-extras = ["tests"]
[tool.cibuildwheel.macos]
archs = ["x86_64", "universal2"] # build fat binaries, or x86-64 for python 3.7
skip = ["cp{38,39,31*}-macosx_x86_64"] # skip x86-only builds where fat binaries are supported
[tool.cibuildwheel.windows]
archs = ["auto64"] # arm64 windows builds not yet supported
[tool.cibuildwheel.linux]
skip = ["cp37-musllinux*", "*musllinux_aarch64*"] # skip targets without available Pillow wheels
manylinux-x86_64-image = "manylinux2014"
manylinux-aarch64-image = "manylinux2014"
[tool.black]
line-length = 120 # 80-column is stupid
target-version = ['py37', 'py38', 'py39', 'py310', 'py310']
skip-string-normalization = true

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -122,4 +122,7 @@ uint16_t Color::Pack565Unscaled() const { return Pack565Unscaled(r, g, b); }
Color Color::ScaleTo565() const { return Color(scale8To5(r), scale8To6(g), scale8To5(b)); }
Color Color::ScaleFrom565() const { return Color(scale5To8(r), scale6To8(g), scale5To8(b)); }
bool Color::operator==(const Color &Rhs) const { return r == Rhs.r && g == Rhs.g && b == Rhs.b && a == Rhs.a; }
bool Color::operator!=(const Color &Rhs) const { return !(Rhs == *this); }
} // namespace quicktex

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -51,7 +51,8 @@ class Color {
static Color Min(const Color &A, const Color &B);
static Color Max(const Color &A, const Color &B);
bool operator==(const Color &Rhs) const { return r == Rhs.r && g == Rhs.g && b == Rhs.b && a == Rhs.a; }
bool operator==(const Color &Rhs) const;
bool operator!=(const Color &Rhs) const;
uint8_t operator[](size_t index) const {
assert(index < 4);

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,2 +1,8 @@
from _quicktex import *
from _quicktex import __version__
try:
from _quicktex import *
from _quicktex import __version__
except ImportError as e:
if 'libomp.dylib' in e.msg:
print('\033[41m\033[01mERROR: LIBOMP NOT FOUND! PLEASE INSTALL IT WITH \033[04m`brew install libomp`\033[0m')
print('original error message:')
raise e

View File

@ -1,6 +1,7 @@
import click
from quicktex.cli.encode import encode
from quicktex.cli.decode import decode
from quicktex.cli.encode import encode
@click.group()

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -96,9 +96,9 @@ template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
auto dst_size = output.NBytes();
if (info.format != py::format_descriptor<uint8_t>::format()) throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
if (info.size < (ssize_t)dst_size) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
if (info.size < (Py_ssize_t)dst_size) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
if (info.ndim == 1) {
if (info.shape[0] < (ssize_t)dst_size) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
if (info.shape[0] < (Py_ssize_t)dst_size) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
if (info.strides[0] != 1) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
} else {
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");
@ -115,9 +115,9 @@ template <typename T> T BufferToPOD(py::buffer buf) {
auto info = buf.request(false);
if (info.format != py::format_descriptor<uint8_t>::format()) throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
if (info.size < (ssize_t)sizeof(T)) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
if (info.size < (Py_ssize_t)sizeof(T)) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
if (info.ndim == 1) {
if (info.shape[0] < (ssize_t)sizeof(T)) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
if (info.shape[0] < (Py_ssize_t)sizeof(T)) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
if (info.strides[0] != 1) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
} else {
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich 2020 <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,7 +1,8 @@
from PIL import Image
from typing import List
import pathlib
from typing import List
import click
from PIL import Image
def get_decoded_extensions(feature: str = 'open') -> List[str]:
@ -39,7 +40,7 @@ def path_pairs(inputs, output, suffix, extension):
"""
if len(inputs) < 1:
raise click.BadArgumentUsage('No input files were provided.')
raise click.BadArgumentUsage('No valid input files were provided.')
inpaths = [pathlib.Path(i) for i in inputs]

View File

@ -1,28 +1,49 @@
import click
import os.path
import quicktex.dds as dds
import quicktex.cli.common as common
import click
from PIL import Image
import quicktex.cli.common as common
import quicktex.dds as dds
@click.command()
@click.option('-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image after converting.")
@click.option(
'-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image after converting."
)
@click.option('-r', '--remove', is_flag=True, help="Remove input images after converting.")
@click.option('-s', '--suffix', type=str, default='', help="Suffix to append to output file(s). Ignored if output is a single file.")
@click.option('-x', '--extension',
callback=common.validate_decoded_extension,
type=str, default='.png', show_default=True,
help="Extension to use for output. Ignored if output is a single file. Output filetype is deduced from this")
@click.option('-o', '--output',
type=click.Path(writable=True), default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.")
@click.option(
'-s',
'--suffix',
type=str,
default='',
help="Suffix to append to output file(s). Ignored if output is a single file.",
)
@click.option(
'-x',
'--extension',
callback=common.validate_decoded_extension,
type=str,
default='.png',
show_default=True,
help="Extension to use for output. Ignored if output is a single file. Output filetype is deduced from this",
)
@click.option(
'-o',
'--output',
type=click.Path(writable=True),
default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.",
)
@click.argument('filenames', nargs=-1, type=click.Path(exists=True, readable=True, dir_okay=False))
def decode(flip, remove, suffix, extension, output, filenames):
"""Decode DDS files to images."""
path_pairs = common.path_pairs(filenames, output, suffix, extension)
with click.progressbar(path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else '') as bar:
with click.progressbar(
path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else ''
) as bar:
for inpath, outpath in bar:
if inpath.suffix != '.dds':
raise click.BadArgumentUsage(f"Input file '{inpath}' is not a DDS file.")

View File

@ -1,13 +1,14 @@
import click
import os
import pathlib
import click
from PIL import Image
import quicktex.cli.common as common
import quicktex.dds as dds
import quicktex.s3tc.bc1
import quicktex.s3tc.bc3
import quicktex.s3tc.bc4
import quicktex.s3tc.bc5
import quicktex.dds as dds
import quicktex.cli.common as common
from PIL import Image
@click.group()
@ -16,23 +17,43 @@ def encode():
@click.command()
@click.option('-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image before converting.")
@click.option(
'-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image before converting."
)
@click.option('-r', '--remove', is_flag=True, help="Remove input images after converting.")
@click.option('-s', '--suffix', type=str, default='', help="Suffix to append to output file(s). Ignored if output is a single file.")
@click.option('-o', '--output',
type=click.Path(writable=True), default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.")
@click.option(
'-s',
'--suffix',
type=str,
default='',
help="Suffix to append to output file(s). Ignored if output is a single file.",
)
@click.option(
'-o',
'--output',
type=click.Path(writable=True),
default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.",
)
@click.argument('filenames', nargs=-1, type=click.Path(exists=True, readable=True, dir_okay=False))
def encode_format(encoder, four_cc, flip, remove, suffix, output, filenames):
def encode_format(encoder, four_cc, flip, remove, suffix, output, filenames, swizzle=False):
filenames = [f for f in filenames if not f.endswith('.dds')]
path_pairs = common.path_pairs(filenames, output, suffix, '.dds')
with click.progressbar(path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else '') as bar:
with click.progressbar(
path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else ''
) as bar:
for inpath, outpath in bar:
image = Image.open(inpath)
if flip:
image = image.transpose(Image.FLIP_TOP_BOTTOM)
if swizzle:
bands = image.split()
one = Image.new('L', image.size, 0xFF)
image = Image.merge('RGBA', (one, bands[1], bands[1], bands[0]))
dds.encode(image, encoder, four_cc).save(outpath)
if remove:
@ -40,17 +61,44 @@ def encode_format(encoder, four_cc, flip, remove, suffix, output, filenames):
@click.command('auto')
@click.option('-l', '--level', type=click.IntRange(0, 18), default=18, help='Quality level to use. Higher values = higher quality, but slower.')
@click.option('-b/-B', '--black/--no-black',
help='[BC1 only] Enable 3-color mode for blocks containing black or very dark pixels. --3color must also be enabled for this to work.'
' (Important: engine/shader MUST ignore decoded texture alpha if this flag is enabled!)')
@click.option('-3/-4', '--3color/--4color', 'threecolor', default=True, help='[BC1 only] Enable 3-color mode for non-black pixels. Higher quality, but slightly slower.')
@click.option('-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image before converting.")
@click.option(
'-l',
'--level',
type=click.IntRange(0, 18),
default=18,
help='Quality level to use. Higher values = higher quality, but slower.',
)
@click.option(
'-b/-B',
'--black/--no-black',
help='[BC1 only] Enable 3-color mode for blocks containing black or very dark pixels. --3color must also be enabled for this to work.'
' (Important: engine/shader MUST ignore decoded texture alpha if this flag is enabled!)',
)
@click.option(
'-3/-4',
'--3color/--4color',
'threecolor',
default=True,
help='[BC1 only] Enable 3-color mode for non-black pixels. Higher quality, but slightly slower.',
)
@click.option(
'-f/-F', '--flip/--no-flip', default=True, show_default=True, help="Vertically flip image before converting."
)
@click.option('-r', '--remove', is_flag=True, help="Remove input images after converting.")
@click.option('-s', '--suffix', type=str, default='', help="Suffix to append to output file(s). Ignored if output is a single file.")
@click.option('-o', '--output',
type=click.Path(writable=True), default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.")
@click.option(
'-s',
'--suffix',
type=str,
default='',
help="Suffix to append to output file(s). Ignored if output is a single file.",
)
@click.option(
'-o',
'--output',
type=click.Path(writable=True),
default=None,
help="Output file or directory. If outputting to a file, input filenames must be only a single item. By default, files are decoded in place.",
)
@click.argument('filenames', nargs=-1, type=click.Path(exists=True, readable=True, dir_okay=False))
def encode_auto(level, black, threecolor, flip, remove, suffix, output, filenames):
"""Encode images to BC1 or BC3, with the format chosen based on each image's alpha channel."""
@ -65,9 +113,14 @@ def encode_auto(level, black, threecolor, flip, remove, suffix, output, filename
bc1_encoder = quicktex.s3tc.bc1.BC1Encoder(level, mode)
bc3_encoder = quicktex.s3tc.bc3.BC3Encoder(level)
filenames = [f for f in filenames if not f.endswith('.dds')]
path_pairs = common.path_pairs(filenames, output, suffix, '.dds')
with click.progressbar(path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else '') as bar:
assert len(filenames) > 0
with click.progressbar(
path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else ''
) as bar:
for inpath, outpath in bar:
image = Image.open(inpath)
@ -90,11 +143,26 @@ def encode_auto(level, black, threecolor, flip, remove, suffix, output, filename
@click.command('bc1')
@click.option('-l', '--level', type=click.IntRange(0, 18), default=18, help='Quality level to use. Higher values = higher quality, but slower.')
@click.option('-b/-B', '--black/--no-black',
help='Enable 3-color mode for blocks containing black or very dark pixels. --3color must also be enabled for this to work.'
' (Important: engine/shader MUST ignore decoded texture alpha if this flag is enabled!)')
@click.option('-3/-4', '--3color/--4color', 'threecolor', default=True, help='Enable 3-color mode for non-black pixels. Higher quality, but slightly slower.')
@click.option(
'-l',
'--level',
type=click.IntRange(0, 18),
default=18,
help='Quality level to use. Higher values = higher quality, but slower.',
)
@click.option(
'-b/-B',
'--black/--no-black',
help='Enable 3-color mode for blocks containing black or very dark pixels. --3color must also be enabled for this to work.'
' (Important: engine/shader MUST ignore decoded texture alpha if this flag is enabled!)',
)
@click.option(
'-3/-4',
'--3color/--4color',
'threecolor',
default=True,
help='Enable 3-color mode for non-black pixels. Higher quality, but slightly slower.',
)
def encode_bc1(level, black, threecolor, **kwargs):
"""Encode images to BC1 (RGB, no alpha)."""
color_mode = quicktex.s3tc.bc1.BC1Encoder.ColorMode
@ -109,10 +177,23 @@ def encode_bc1(level, black, threecolor, **kwargs):
@click.command('bc3')
@click.option('-l', '--level', type=click.IntRange(0, 18), default=18, help='Quality level to use. Higher values = higher quality, but slower.')
def encode_bc3(level, **kwargs):
@click.option(
'-l',
'--level',
type=click.IntRange(0, 18),
default=18,
help='Quality level to use. Higher values = higher quality, but slower.',
)
@click.option(
'-n/-N',
'--normal/--no-normal',
type=bool,
default=False,
help='Perform a BC3nm swizzle, copying the red channel into the alpha [default: no-normal]',
)
def encode_bc3(level, normal, **kwargs):
"""Encode images to BC4 (RGBA, 8-bit interpolated alpha)."""
encode_format.callback(quicktex.s3tc.bc3.BC3Encoder(level), 'DXT5', **kwargs)
encode_format.callback(quicktex.s3tc.bc3.BC3Encoder(level), 'DXT5', swizzle=normal, **kwargs)
@click.command('bc4')

View File

@ -4,12 +4,14 @@ import enum
import os
import struct
import typing
from PIL import Image
import quicktex.image_utils
import quicktex.s3tc.bc1 as bc1
import quicktex.s3tc.bc3 as bc3
import quicktex.s3tc.bc4 as bc4
import quicktex.s3tc.bc5 as bc5
from PIL import Image
class DDSFormat:
@ -165,8 +167,28 @@ class DDSFile:
file.write(DDSFile.magic)
# WRITE HEADER
file.write(struct.pack('<7I44x', DDSFile.header_bytes, int(self.flags), self.size[1], self.size[0], self.pitch, self.depth, self.mipmap_count))
file.write(struct.pack('<2I4s5I', 32, int(self.pfflags), bytes(self.four_cc, 'ascii'), self.pixel_size, *self.pixel_bitmasks))
file.write(
struct.pack(
'<7I44x',
DDSFile.header_bytes,
int(self.flags),
self.size[1],
self.size[0],
self.pitch,
self.depth,
self.mipmap_count,
)
)
file.write(
struct.pack(
'<2I4s5I',
32,
int(self.pf_flags),
bytes(self.four_cc, 'ascii'),
self.pixel_size,
*self.pixel_bitmasks,
)
)
file.write(struct.pack('<4I4x', *self.caps))
assert file.tell() == 4 + DDSFile.header_bytes, 'error writing file: incorrect header size'
@ -253,10 +275,11 @@ def read(path: os.PathLike) -> DDSFile:
def encode(image: Image.Image, encoder, four_cc: str, mip_count: typing.Optional[int] = None) -> DDSFile:
if image.mode != 'RGBA' or image.mode != 'RGBX':
mode = 'RGBA' if 'A' in image.mode else 'RGBX'
image.apply_transparency() # why is this necessary what
image = image.convert(mode)
sizes = quicktex.image_utils.mip_sizes(image.size, mip_count)
images = [image] + [image.resize(size, Image.BILINEAR) for size in sizes[1:]]
images = [image] + [quicktex.image_utils.resize_no_premultiply(image, size) for size in sizes[1:]]
dds = DDSFile()
for i in images:

View File

@ -1,8 +1,9 @@
"""Various utilities for working with Pillow images"""
from PIL import Image
from typing import List, Tuple, Optional
import math
from typing import List, Tuple, Optional
from PIL import Image
def mip_sizes(dimensions: Tuple[int, int], mip_count: Optional[int] = None) -> List[Tuple[int, int]]:
@ -32,3 +33,20 @@ def mip_sizes(dimensions: Tuple[int, int], mip_count: Optional[int] = None) -> L
dimensions = tuple([max(dim // 2, 1) for dim in dimensions])
return chain
def resize_no_premultiply(image: Image.Image, size: Tuple[int, int]) -> Image.Image:
"""
Resize an image without premulitplying the alpha. Required due to a quick in Pillow
:param image: Image to resize
:param size: Size to resize to
:return: The resized image
"""
if image.mode == 'RGBA':
rgb = image.convert('RGB').resize(size, Image.BILINEAR)
a = image.getchannel('A').resize(size, Image.BILINEAR)
rgb.putalpha(a)
return rgb
else:
return image.resize(size, Image.BILINEAR)

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -41,4 +41,7 @@ void BC1Block::SetSelectors(const BC1Block::SelectorArray& unpacked) {
_selectors = MapArray(unpacked, Pack<uint8_t, uint8_t, SelectorBits, Width>);
}
bool BC1Block::operator==(const BC1Block& Rhs) const { return _color0 == Rhs._color0 && _color1 == Rhs._color1 && _selectors == Rhs._selectors; }
bool BC1Block::operator!=(const BC1Block& Rhs) const { return !(Rhs == *this); }
} // namespace quicktex::s3tc

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -121,7 +121,7 @@ class alignas(8) BC1Block {
bool Is3Color() const { return GetColor0Raw() <= GetColor1Raw(); }
bool operator==(const BC1Block& other) const = default;
bool operator!=(const BC1Block& other) const = default;
bool operator==(const BC1Block& Rhs) const;
bool operator!=(const BC1Block& Rhs) const;
};
} // namespace quicktex::s3tc

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -58,7 +58,7 @@ template <size_t N> class OrderTable {
static bool Generate() {
static_assert(N == 4 || N == 3);
table_mutex.lock();
std::scoped_lock{table_mutex};
if (!generated) {
hashes = new std::array<Hash, HashCount>();
factors = new std::array<Vector4, OrderCount>();
@ -85,8 +85,6 @@ template <size_t N> class OrderTable {
generated = true;
}
table_mutex.unlock();
assert(generated);
return true;
}

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -54,7 +54,7 @@ class alignas(8) BC3Block {
color_block = blocks.second;
}
bool operator==(const BC3Block &other) const = default;
bool operator!=(const BC3Block &other) const = default;
bool operator==(const BC3Block &Rhs) const { return alpha_block == Rhs.alpha_block && color_block == Rhs.color_block; }
bool operator!=(const BC3Block &Rhs) const { return !(Rhs == *this); }
};
} // namespace quicktex::s3tc

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -19,8 +19,8 @@
#include "BC4Block.h"
#include <stdexcept>
#include <algorithm>
#include <stdexcept>
#include "../../util.h"
@ -63,4 +63,7 @@ std::array<uint8_t, 8> BC4Block::GetValues8() const {
static_cast<uint8_t>((alpha0 * 2 + alpha1 * 5) / 7),
static_cast<uint8_t>((alpha0 + alpha1 * 6) / 7)};
}
bool BC4Block::operator==(const BC4Block& Rhs) const { return alpha0 == Rhs.alpha0 && alpha1 == Rhs.alpha1 && _selectors == Rhs._selectors; }
bool BC4Block::operator!=(const BC4Block& Rhs) const { return !(Rhs == *this); }
} // namespace quicktex::s3tc

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -97,8 +97,8 @@ class alignas(8) BC4Block {
/// The interpolated values of this block as an array of 8 integers.
std::array<uint8_t, 8> GetValues() const { return Is6Value() ? GetValues6() : GetValues8(); }
bool operator==(const BC4Block& other) const = default;
bool operator!=(const BC4Block& other) const = default;
bool operator==(const BC4Block& Rhs) const;
bool operator!=(const BC4Block& Rhs) const;
private:
std::array<uint8_t, 8> GetValues6() const;

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
@ -53,7 +53,7 @@ class alignas(8) BC5Block {
chan1_block = pair.second;
}
bool operator==(const BC5Block &other) const = default;
bool operator!=(const BC5Block &other) const = default;
bool operator==(const BC5Block &Rhs) const { return chan0_block == Rhs.chan0_block && chan1_block == Rhs.chan1_block; }
bool operator!=(const BC5Block &Rhs) const { return !(Rhs == *this); }
};
} // namespace quicktex::s3tc

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com> and licenced under the public domain
This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain

View File

@ -1,16 +1,14 @@
import os
import sys
import glob
import re
import subprocess
import sys
from setuptools import setup, Extension, find_packages
import pybind11
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
project_path = os.path.dirname(os.path.realpath(__file__))
with open(os.path.join(project_path, 'README.md')) as f:
readme = f.read()
# A CMakeExtension needs a sourcedir instead of a file list.
# The name must be the _single_ output extension from the CMake build.
@ -24,6 +22,7 @@ class CMakeExtension(Extension):
class CMakeBuild(build_ext):
def build_extension(self, ext):
from setuptools_scm import get_version
version = get_version(root='.', relative_to=__file__)
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
@ -32,7 +31,9 @@ class CMakeBuild(build_ext):
if not extdir.endswith(os.path.sep):
extdir += os.path.sep
cfg = "Debug" if self.debug else "Release"
cfg = "Debug" if self.debug else "RelWithDebInfo"
if 'QUICKTEX_DEBUG' in os.environ:
cfg = "Debug"
# CMake lets you override the generator - we need to check this.
# Can be set with Conda-Build, for example.
@ -41,9 +42,15 @@ class CMakeBuild(build_ext):
# Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON
cmake_args = [
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}".format(extdir),
"-Dpybind11_DIR={}".format(pybind11.get_cmake_dir()),
"-DPython_EXECUTABLE={}".format(sys.executable),
"-DQUICKTEX_VERSION_INFO={}".format(version),
"-DPython_ROOT_DIR={}".format(os.path.dirname(sys.executable)),
"-DQUICKTEX_VERSION_INFO={}".format(version), # include version info in module
"-DQUICKTEX_MODULE_ONLY=TRUE", # only build the module, not the wrapper
"-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm
# clear cached make program binary, see https://github.com/pypa/setuptools/issues/2912
"-U",
"CMAKE_MAKE_PROGRAM",
]
build_args = []
@ -64,12 +71,7 @@ class CMakeBuild(build_ext):
contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"})
# Convert distutils Windows platform specifiers to CMake -A arguments
plat_to_cmake = {
"win32": "Win32",
"win-amd64": "x64",
"win-arm32": "ARM",
"win-arm64": "ARM64",
}
plat_to_cmake = {"win32": "Win32", "win-amd64": "x64", "win-arm32": "ARM", "win-arm64": "ARM64"}
# Specify the arch if using MSVC generator, but only if it doesn't
# contain a backward-compatibility arch spec already in the
@ -79,11 +81,15 @@ class CMakeBuild(build_ext):
# Multi-config generators have a different way to specify configs
if not single_config:
cmake_args += [
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir)
]
cmake_args += ["-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir)]
build_args += ["--config", cfg]
if sys.platform.startswith("darwin"):
# Cross-compile support for macOS - respect ARCHFLAGS if set
archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", ""))
if archs:
cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))]
# Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level
# across all generators.
if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
@ -96,57 +102,10 @@ class CMakeBuild(build_ext):
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
subprocess.check_call(
["cmake", ext.sourcedir] + cmake_args, cwd=self.build_temp
)
subprocess.check_call(
["cmake", "--build", ".", "--target", ext.name] + build_args, cwd=self.build_temp
)
subprocess.check_call(["cmake", ext.sourcedir] + cmake_args, cwd=self.build_temp)
subprocess.check_call(["cmake", "--build", ".", "--target", ext.name] + build_args, cwd=self.build_temp)
# Find stub files
stubs = [path.replace('quicktex/', '') for path in glob.glob('quicktex/**/*.pyi', recursive=True)]
# The information here can also be placed in setup.cfg - better separation of
# logic and declaration, and simpler if you include description/version in a file.
setup(
name="quicktex",
use_scm_version=True,
author="Andrew Cassidy",
author_email="drewcassidy@me.com",
description="A fast block compression library for python",
url='https://github.com/drewcassidy/quicktex',
long_description=readme,
long_description_content_type='text/markdown',
python_requires=">=3.7",
ext_modules=[CMakeExtension("_quicktex")],
cmdclass={"build_ext": CMakeBuild},
packages=['quicktex'],
package_dir={'': '.'},
package_data={'': ['py.typed'] + stubs},
include_package_data=True,
install_requires=["Pillow", "click"],
extras_require={
"tests": ["nose", "parameterized"],
"docs": ["sphinx", "myst-parser", "sphinx-rtd-theme"],
"stubs": ["pybind11-stubgen"],
},
entry_points={
'console_scripts': ['quicktex = quicktex.__main__:main']
},
zip_safe=False,
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: C++'
],
)
setup(use_scm_version=True, ext_modules=[CMakeExtension("_quicktex")], cmdclass={"build_ext": CMakeBuild})

View File

@ -1,9 +1,3 @@
import os.path
# Some checks to run before tests can begin
images_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'images')
assert os.path.isdir(images_path), 'test images repo not present'
assert os.path.isfile(os.path.join(images_path, '__init__.py')), 'images __init__.py not present, is the test image repo present?'
bp_size = os.path.getsize(os.path.join(images_path, 'Boilerplate.png'))
assert bp_size == 955989, 'Boilerplate.png is the wrong size, is the test image repo checked out with LFS enabled?'

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

BIN
tests/images/Bun.afdesign Normal file

Binary file not shown.

BIN
tests/images/Bun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

32
tests/images/__init__.py Normal file
View File

@ -0,0 +1,32 @@
from PIL import Image
from quicktex.s3tc.bc1 import BC1Block
from quicktex.s3tc.bc4 import BC4Block
from quicktex import RawTexture
import os.path
image_path = os.path.dirname(os.path.realpath(__file__))
class BC1Blocks:
class Entry:
def __init__(self, filename, block):
path = os.path.join(image_path, 'bc1', filename)
self.image = Image.open(path).convert('RGBA')
self.texture = RawTexture.frombytes(self.image.tobytes('raw', 'RGBA'), *self.image.size)
self.block = block
greyscale = Entry('greyscale_unpacked.png', BC1Block.frombytes(b'\xFF\xFF\x49\x4A\x78\x78\x78\x78'))
three_color = Entry('3color_unpacked.png', BC1Block.frombytes(b'\xE0\x07\x00\xF8\x29\x29\x29\x29'))
three_color_black = Entry('3color_black_unpacked.png', BC1Block.frombytes(b'\xE0\x07\x00\xF8\x27\x27\x27\x27'))
class BC4Blocks:
class Entry:
def __init__(self, filename, block):
path = os.path.join(image_path, 'bc4', filename)
self.image = Image.open(path).convert('RGBA')
self.texture = RawTexture.frombytes(self.image.tobytes('raw', 'RGBA'), *self.image.size)
self.block = block
six_value = Entry('6value.png', BC4Block(8, 248, [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2))
eight_value = Entry('8value.png', BC4Block(240, 16, [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2))

BIN
tests/images/bc1/3color.dds Normal file

Binary file not shown.

BIN
tests/images/bc1/3color.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

BIN
tests/images/bc4/6value.dds Normal file

Binary file not shown.

BIN
tests/images/bc4/6value.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

BIN
tests/images/bc4/8value.dds Normal file

Binary file not shown.

BIN
tests/images/bc4/8value.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

View File

@ -1,44 +0,0 @@
/* Quicktex Texture Compression Library
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
and licenced under the public domain
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// This file allows for easy debugging in CLion or other IDEs that dont natively support cross-debugging between Python and C++
#include <pybind11/embed.h>
#include <array>
#include <string>
namespace py = pybind11;
using namespace pybind11::literals;
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
int main() {
py::scoped_interpreter guard{};
py::module_ site = py::module_::import("site");
site.attr("addsitedir")(CUSTOM_SYS_PATH);
py::module_ nose = py::module_::import("nose");
py::module_ tests = py::module_::import("tests");
py::list argv(1);
nose.attr("runmodule")("name"_a = "tests.test_bc1", "exit"_a = false);
}

Some files were not shown because too many files have changed in this diff Show More