Kinda working extension module

hotfix/mipmap-alpha-fix
Andrew Cassidy 3 years ago
parent 19028db209
commit 289a4fa001

3
.gitignore vendored

@ -1,5 +1,8 @@
# Python
env/
dist/
build/
*.egg-info
# IDEs
**/.idea

@ -10,7 +10,7 @@ add_subdirectory(extern/pybind11)
# Collect source files
file(GLOB SOURCE_FILES "src/*.cpp" "src/BC*/*.cpp")
file(GLOB HEADER_FILES "src/*.h" "src/BC*/*.h")
file(GLOB PYTHON_FILES "src/python/*.cpp" "src/python/*.h")
file(GLOB PYTHON_FILES "python/*.cpp" "python/*.h")
file(GLOB TEST_FILES "src/test/*.c" "src/test/*.cpp" "src/test/*.h")
# Organize source files together for some IDEs
@ -38,7 +38,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
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++ -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined")
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
endif ()

@ -0,0 +1,63 @@
/* Python-rgbcx 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/>.
*/
#include <pybind11/pybind11.h>
#include "../src/BC1/BC1Encoder.h"
#include "../src/BlockEncoder.h"
#include "../src/bitwiseEnums.h"
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
namespace py = pybind11;
namespace rgbcx::bindings {
void InitBC1(py::module_ &m) {
auto block_encoder = py::type::of<BlockEncoder>();
py::class_<BC1Encoder> bc1_encoder(m, "BC1Encoder", block_encoder);
bc1_encoder.def(py::init<>());
using Flags = BC1Encoder::Flags;
py::enum_<Flags>(bc1_encoder, "Flags", py::arithmetic())
.value("UseLikelyTotalOrderings", Flags::UseLikelyTotalOrderings)
.value("TwoLeastSquaresPasses", Flags::TwoLeastSquaresPasses)
.value("Use3ColorBlocksForBlackPixels", Flags::Use3ColorBlocksForBlackPixels)
.value("Use3ColorBlocks", Flags::Use3ColorBlocks)
.value("Iterative", Flags::Iterative)
.value("Use6PowerIters", Flags::Use6PowerIters)
.value("Exhaustive", Flags::Exhaustive)
.value("TryAllInitialEndpoints", Flags::TryAllInitialEndpoints)
.def("__invert__", [](Flags f1) { return ~unsigned(f1); })
.def("__and__", [](Flags f1, Flags f2) { return unsigned(f1) & unsigned(f2); })
.def("__rand__", [](Flags f1, Flags f2) { return unsigned(f1) & unsigned(f2); })
.def("__or__", [](Flags f1, Flags f2) { return unsigned(f1) | unsigned(f2); })
.def("__ror__", [](Flags f1, Flags f2) { return unsigned(f1) | unsigned(f2); })
.def("__xor__", [](Flags f1, Flags f2) { return unsigned(f1) ^ unsigned(f2); })
.def("__rxor__", [](Flags f1, Flags f2) { return unsigned(f2) ^ unsigned(f1); });
py::enum_<BC1Encoder::EndpointMode>(bc1_encoder, "EndpointMode")
.value("LeastSquares", BC1Encoder::EndpointMode::LeastSquares)
.value("BoundingBox", BC1Encoder::EndpointMode::BoundingBox)
.value("BoundingBoxInt", BC1Encoder::EndpointMode::BoundingBoxInt)
.value("PCA", BC1Encoder::EndpointMode::PCA);
}
} // namespace rgbcx::bindings

@ -0,0 +1,64 @@
/* Python-rgbcx 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/>.
*/
#include "../src/BlockEncoder.h"
#include <pybind11/pybind11.h>
#include <stdexcept>
#include "../src/bitwiseEnums.h"
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
namespace py = pybind11;
namespace rgbcx::bindings {
py::bytes EncodeImage(const BlockEncoder &self, py::bytes decoded, unsigned image_width, unsigned image_height) {
if (image_width % self.BlockWidth() != 0) throw std::invalid_argument("Width is not an even multiple of block_width");
if (image_height % self.BlockHeight() != 0) throw std::invalid_argument("Height is not an even multiple of block_height");
if (image_width == 0 || image_height == 0) throw std::invalid_argument("Image has zero size");
size_t size = image_width * image_height;
size_t block_size = (size / (self.BlockHeight() * self.BlockWidth())) * self.BlockSize();
size_t color_size = size * sizeof(Color);
std::string encoded_str = std::string(block_size, 0);
std::string decoded_str = (std::string)decoded; // decoded data is copied here, unfortunately
if (decoded_str.size() != color_size) throw std::invalid_argument("Incompatible data: image width and height do not match the size of the decoded image");
self.EncodeImage(reinterpret_cast<uint8_t *>(encoded_str.data()), reinterpret_cast<Color *>(decoded_str.data()), image_width, image_height);
auto bytes = py::bytes(encoded_str); // encoded data is copied here, unfortunately
return bytes;
}
void InitBlockEncoder(py::module_ &m) {
py::class_<BlockEncoder> block_encoder(m, "BlockEncoder");
block_encoder.def("encode_image", &EncodeImage);
block_encoder.def_property_readonly("block_size", &BlockEncoder::BlockSize);
block_encoder.def_property_readonly("block_width", &BlockEncoder::BlockWidth);
block_encoder.def_property_readonly("block_height", &BlockEncoder::BlockHeight);
}
} // namespace rgbcx::bindings

@ -18,13 +18,21 @@
*/
#include <pybind11/pybind11.h>
#include "../BC1/BC1Encoder.h"
#include "../src/BlockEncoder.h"
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
namespace py = pybind11;
namespace rgbcx::bindings {
void InitBlockEncoder(py::module_ &m);
void InitBC1(py::module_ &m);
PYBIND11_MODULE(python_rgbcx, m) {
m.doc() = "More Stuff";
}
InitBlockEncoder(m);
InitBC1(m);
}
} // namespace python_rgbcx::py

@ -34,7 +34,7 @@ namespace rgbcx {
class Interpolator;
class Vector4;
class BC1Encoder final : public BlockEncoder<BC1Block, 4, 4> {
class BC1Encoder final : public BlockEncoderTemplate<BC1Block, 4, 4> {
public:
using InterpolatorPtr = std::shared_ptr<Interpolator>;

@ -29,7 +29,7 @@
namespace rgbcx {
class BC4Encoder : public BlockEncoder<BC4Block, 4, 4> {
class BC4Encoder : public BlockEncoderTemplate<BC4Block, 4, 4> {
public:
BC4Encoder(const uint8_t channel) : _channel(channel) { assert(channel < 4); }

@ -0,0 +1,25 @@
/* Python-rgbcx 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/>.
*/
#include "BlockEncoder.h"
#include "BC1/BC1Encoder.h"
namespace rgbcx {
std::shared_ptr<BlockEncoder> rgbcx::BlockEncoder::MakeEncoder(std::string fourcc) { return std::make_shared<BC1Encoder>(); }
} // namespace rgbcx

@ -21,22 +21,37 @@
#include <climits>
#include <cstdint>
#include <memory>
#include <string>
#include "BlockView.h"
namespace rgbcx {
template <class B, size_t M, size_t N> class BlockEncoder {
class BlockEncoder {
public:
using EncoderPtr = std::shared_ptr<BlockEncoder>;
virtual ~BlockEncoder() = default;
virtual void EncodeImage(uint8_t *encoded, Color *decoded, unsigned image_width, unsigned image_height) const = 0;
virtual size_t BlockSize() const = 0;
virtual size_t BlockWidth() const = 0;
virtual size_t BlockHeight() const = 0;
static EncoderPtr MakeEncoder(std::string fourcc);
};
template <class B, size_t M, size_t N> class BlockEncoderTemplate : public BlockEncoder {
public:
using DecodedBlock = ColorBlockView<M, N>;
using EncodedBlock = B;
BlockEncoder() noexcept = default;
virtual ~BlockEncoder() noexcept = default;
BlockEncoderTemplate() noexcept = default;
virtual ~BlockEncoderTemplate() noexcept = default;
virtual void EncodeBlock(DecodedBlock pixels, EncodedBlock *dest) const = 0;
virtual void EncodeImage(uint8_t *encoded, Color *decoded, unsigned image_width, unsigned image_height) {
virtual void EncodeImage(uint8_t *encoded, Color *decoded, unsigned image_width, unsigned image_height) const override {
assert(image_width % N == 0);
assert(image_width % M == 0);
@ -61,11 +76,13 @@ template <class B, size_t M, size_t N> class BlockEncoder {
unsigned top_left = pixel_x + (pixel_y * image_width);
auto src = DecodedBlock(&decoded[top_left], (int)image_width);
// if (pixel_x != 684 || pixel_y != 492) continue;
EncodeBlock(src, &blocks[x + block_width * y]);
}
}
}
virtual size_t BlockSize() const override { return sizeof(B); }
virtual size_t BlockWidth() const override { return N; }
virtual size_t BlockHeight() const override { return M; }
};
} // namespace rgbcx

@ -1,6 +0,0 @@
#! /usr/bin/bash
set dir (status dirname)
source "$dir"/../env/bin/activate.fish
pip install "$dir"/..
Loading…
Cancel
Save