diff --git a/CMakeLists.txt b/CMakeLists.txt index 62c2b4c..fcd4ba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,10 +30,7 @@ file(GLOB HEADER_FILES file(GLOB TEST_FILES "tests/*.cpp") -set(PYTHON_FILES - "quicktex/bindings/Module.cpp" - "quicktex/s3tc/bindings/Decoders.cpp" - "quicktex/s3tc/bindings/Encoders.cpp") +file(GLOB_RECURSE PYTHON_FILES "src/**/*.py") # Organize source files together for some IDEs source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_FILES} ${HEADER_FILES} ${PYTHON_FILES}) @@ -41,8 +38,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCE_FILES} ${HEADER_FIL # Add python module pybind11_add_module(_quicktex ${SOURCE_FILES} - ${HEADER_FILES} - ${PYTHON_FILES}) + ${HEADER_FILES}) add_executable(test_quicktex ${SOURCE_FILES} diff --git a/quicktex/BlockDecoder.h b/quicktex/BlockDecoder.h index 48abca0..5b779d6 100644 --- a/quicktex/BlockDecoder.h +++ b/quicktex/BlockDecoder.h @@ -25,9 +25,9 @@ #include #include -#include "../BlockView.h" -#include "../ndebug.h" -#include "../util.h" +#include "BlockView.h" +#include "ndebug.h" +#include "util.h" namespace quicktex { diff --git a/quicktex/BlockEncoder.h b/quicktex/BlockEncoder.h index 23ec151..0a936b5 100644 --- a/quicktex/BlockEncoder.h +++ b/quicktex/BlockEncoder.h @@ -24,7 +24,7 @@ #include #include -#include "../BlockView.h" +#include "BlockView.h" namespace quicktex { diff --git a/quicktex/s3tc/bindings/Decoders.cpp b/quicktex/_bindings.cpp similarity index 60% rename from quicktex/s3tc/bindings/Decoders.cpp rename to quicktex/_bindings.cpp index 9ba6534..f51e42e 100644 --- a/quicktex/s3tc/bindings/Decoders.cpp +++ b/quicktex/_bindings.cpp @@ -18,22 +18,35 @@ */ #include - -#include -#include -#include -#include -#include - -#include "../../BlockDecoder.h" -#include "../bc1/BC1Decoder.h" -#include "../bc3/BC3Decoder.h" -#include "../bc4/BC4Decoder.h" -#include "../bc5/BC5Decoder.h" +#include "BlockEncoder.h" +#include "BlockDecoder.h" namespace py = pybind11; namespace quicktex::bindings { +void InitS3TC(py::module_ &m); + +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(encoded_str.data()), reinterpret_cast(decoded_str.data()), image_width, image_height); + + auto bytes = py::bytes(encoded_str); // encoded data is copied here, unfortunately + + return bytes; +} + py::bytes DecodeImage(const BlockDecoder &self, py::bytes encoded, 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"); @@ -55,7 +68,9 @@ py::bytes DecodeImage(const BlockDecoder &self, py::bytes encoded, unsigned imag return bytes; } -void InitDecoders(py::module_ &m) { +PYBIND11_MODULE(_quicktex, m) { + m.doc() = "More Stuff"; + // BlockDecoder py::class_ block_decoder(m, "BlockDecoder"); @@ -64,32 +79,15 @@ void InitDecoders(py::module_ &m) { block_decoder.def_property_readonly("block_width", &BlockDecoder::BlockWidth); block_decoder.def_property_readonly("block_height", &BlockDecoder::BlockHeight); - // BC1Decoder - py::class_ bc1_decoder(m, "BC1Decoder", block_decoder); + // BlockEncoder + py::class_ block_encoder(m, "BlockEncoder"); - bc1_decoder.def(py::init(), py::arg("interpolator") = Interpolator::Type::Ideal, py::arg("write_alpha") = false); - bc1_decoder.def_property_readonly("interpolator_type", &BC1Decoder::GetInterpolatorType); - bc1_decoder.def_readwrite("write_alpha", &BC1Decoder::write_alpha); + 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); - // BC3Decoder - py::class_ bc3_decoder(m, "BC3Decoder", block_decoder); - - bc3_decoder.def(py::init(), py::arg("type") = Interpolator::Type::Ideal); - bc3_decoder.def_property_readonly("bc1_decoder", &BC3Decoder::GetBC1Decoder); - bc3_decoder.def_property_readonly("bc4_decoder", &BC3Decoder::GetBC4Decoder); - - // BC4Decoder - py::class_ bc4_decoder(m, "BC4Decoder", block_decoder); - - bc4_decoder.def(py::init(), py::arg("channel") = 3); - bc4_decoder.def_property("channel", &BC4Decoder::GetChannel, &BC4Decoder::SetChannel); - - // BC5Decoder - py::class_ bc5_decoder(m, "BC5Decoder", block_decoder); - - bc5_decoder.def(py::init(), py::arg("chan0") = 0, py::arg("chan1") = 1); - bc5_decoder.def_property("channels", &BC5Decoder::GetChannels, &BC5Decoder::SetChannels); - bc5_decoder.def_property_readonly("bc4_decoders", &BC5Decoder::GetBC4Decoders); + InitS3TC(m); } } // namespace quicktex::bindings \ No newline at end of file diff --git a/quicktex/s3tc/Interpolator.cpp b/quicktex/s3tc/Interpolator.cpp index ac5babb..0923186 100644 --- a/quicktex/s3tc/Interpolator.cpp +++ b/quicktex/s3tc/Interpolator.cpp @@ -26,67 +26,7 @@ #include "../util.h" -namespace quicktex { - -/* -Interpolator::Interpolator() { - PrepSingleColorTables(_single_match5, _single_match5_half, 5); - PrepSingleColorTables(_single_match5, _single_match5_half, 6); -} - -void Interpolator::PrepSingleColorTables(const MatchListPtr &matchTable, const MatchListPtr &matchTableHalf, int len) { - int size = 1 << len; - - assert((len == 5 && size == Size5) || (len == 6 && size == size6)); - - const uint8_t *expand = (len == 5) ? &Expand5[0] : &Expand6[0]; - - bool ideal = IsIdeal(); - bool use_e = useExpandedInMatch(); - - for (int i = 0; i < match_count; i++) { - int lowest_error = 256; - int lowest_half_error = 256; - - for (int low = 0; low < size; low++) { - const int low_e = expand[low]; - const int low_val = use_e ? low_e : low; - - for (int high = 0; high < size; high++) { - const int high_e = expand[high]; - const int high_val = use_e ? high_e : high; - - int v = (len == 5) ? Interpolate5(high_val, low_val) : Interpolate6(high_val, low_val); - int v_half = (len == 5) ? InterpolateHalf5(low_val, high_val) : InterpolateHalf6(low_val, high_val); - - int error = PrepSingleColorTableEntry(matchTable, v, i, low, high, low_e, high_e, lowest_error, false, ideal); - int half_error = PrepSingleColorTableEntry(matchTableHalf, v, i, low, high, low_e, high_e, lowest_error, true, ideal); - - if (error < lowest_error) lowest_error = error; - if (half_error < lowest_half_error) lowest_half_error = half_error; - } - } - } -} -int Interpolator::PrepSingleColorTableEntry(const MatchListPtr &matchTable, int v, int i, int low, int high, int low_e, int high_e, int lowest_error, bool half, - bool ideal) { - int e = iabs(v - i); - - // We only need to factor in 3% error in BC1 ideal mode. - if (ideal) e += (iabs(high_e - low_e) * 3) / 100; - - // Favor equal endpoints, for lower error on actual GPU's which approximate the interpolation. - if ((e < lowest_error) || (e == lowest_error && low == high)) { - assert(e <= UINT8_MAX); - - auto &entry = (*matchTable)[i]; - entry.low = low; - entry.high = high; - entry.error = e; - } - - return e; -}*/ +namespace quicktex::s3tc { // region Interpolator implementation std::unique_ptr Interpolator::MakeInterpolator(Interpolator::Type type) { @@ -196,4 +136,4 @@ uint8_t InterpolatorAMD::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 uint8_t InterpolatorAMD::InterpolateHalf8(uint8_t v0, uint8_t v1) const { return (v0 + v1 + 1) >> 1; } // endregion -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/Interpolator.h b/quicktex/s3tc/Interpolator.h index ad24af2..9309a60 100644 --- a/quicktex/s3tc/Interpolator.h +++ b/quicktex/s3tc/Interpolator.h @@ -24,7 +24,7 @@ #include "../Color.h" // for Color -namespace quicktex { +namespace quicktex::s3tc { class Interpolator { public: @@ -171,4 +171,4 @@ class InterpolatorAMD : public Interpolator { Type GetType() const noexcept override { return Type::AMD; } }; -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/__init__.py b/quicktex/s3tc/__init__.py new file mode 100644 index 0000000..067d55b --- /dev/null +++ b/quicktex/s3tc/__init__.py @@ -0,0 +1 @@ +from _quicktex._s3tc import * \ No newline at end of file diff --git a/quicktex/bindings/Module.cpp b/quicktex/s3tc/_bindings.cpp similarity index 69% rename from quicktex/bindings/Module.cpp rename to quicktex/s3tc/_bindings.cpp index 7273a84..87bc329 100644 --- a/quicktex/bindings/Module.cpp +++ b/quicktex/s3tc/_bindings.cpp @@ -19,26 +19,32 @@ #include -#include "../s3tc/Interpolator.h" +#include "Interpolator.h" namespace py = pybind11; namespace quicktex::bindings { -void InitEncoders(py::module_ &m); -void InitDecoders(py::module_ &m); +using namespace quicktex; +using namespace quicktex::s3tc; -PYBIND11_MODULE(_quicktex, m) { - m.doc() = "More Stuff"; +void InitBC1(py::module_ &s3tc); +void InitBC3(py::module_ &s3tc); +void InitBC4(py::module_ &s3tc); +void InitBC5(py::module_ &s3tc); + +void InitS3TC(py::module_ &m) { + py::module_ s3tc = m.def_submodule("_s3tc", "s3tc compression library based on rgbcx.h written by Richard Goldreich"); using IType = Interpolator::Type; - py::enum_(m, "InterpolatorType") + py::enum_(s3tc, "InterpolatorType") .value("Ideal", IType::Ideal) .value("IdealRound", IType::IdealRound) .value("Nvidia", IType::Nvidia) .value("AMD", IType::AMD); - InitEncoders(m); - InitDecoders(m); + InitBC1(s3tc); + InitBC3(s3tc); + InitBC4(s3tc); + InitBC5(s3tc); } - -} // namespace quicktex::bindings \ No newline at end of file +} // namespace quicktex::bindings diff --git a/quicktex/s3tc/bc1/BC1Block.h b/quicktex/s3tc/bc1/BC1Block.h index 4adc4ba..b618e1e 100644 --- a/quicktex/s3tc/bc1/BC1Block.h +++ b/quicktex/s3tc/bc1/BC1Block.h @@ -27,7 +27,7 @@ #include "../../Color.h" #include "../../util.h" -namespace quicktex { +namespace quicktex::s3tc { #pragma pack(push, 1) class BC1Block { @@ -82,4 +82,4 @@ class BC1Block { std::array selectors; }; #pragma pack(pop) -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/BC1Decoder.cpp b/quicktex/s3tc/bc1/BC1Decoder.cpp index 26c6b87..6b64f56 100644 --- a/quicktex/s3tc/bc1/BC1Decoder.cpp +++ b/quicktex/s3tc/bc1/BC1Decoder.cpp @@ -28,7 +28,7 @@ #include "../../ndebug.h" #include "BC1Block.h" -namespace quicktex { +namespace quicktex::s3tc { void BC1Decoder::DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcept(ndebug) { const auto l = block->GetLowColor(); const auto h = block->GetHighColor(); @@ -49,4 +49,4 @@ void BC1Decoder::DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcep } } } -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc1/BC1Decoder.h b/quicktex/s3tc/bc1/BC1Decoder.h index 16652b0..a1701f3 100644 --- a/quicktex/s3tc/bc1/BC1Decoder.h +++ b/quicktex/s3tc/bc1/BC1Decoder.h @@ -28,7 +28,7 @@ #include "../Interpolator.h" #include "BC1Block.h" -namespace quicktex { +namespace quicktex::s3tc { class BC1Decoder final : public BlockDecoderTemplate { public: using InterpolatorPtr = std::shared_ptr; @@ -45,4 +45,4 @@ class BC1Decoder final : public BlockDecoderTemplate { private: const InterpolatorPtr _interpolator; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc1/BC1Encoder.cpp b/quicktex/s3tc/bc1/BC1Encoder.cpp index 9adcb93..f1de5c1 100644 --- a/quicktex/s3tc/bc1/BC1Encoder.cpp +++ b/quicktex/s3tc/bc1/BC1Encoder.cpp @@ -39,8 +39,7 @@ #include "OrderTable.h" #include "SingleColorTable.h" -namespace quicktex { -using namespace BC1; +namespace quicktex::s3tc { // constructors @@ -941,4 +940,4 @@ void BC1Encoder::EndpointSearch(Color4x4 &pixels, EncodeResults &block) const { } } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/BC1Encoder.h b/quicktex/s3tc/bc1/BC1Encoder.h index 7ebf83a..3ccb9d9 100644 --- a/quicktex/s3tc/bc1/BC1Encoder.h +++ b/quicktex/s3tc/bc1/BC1Encoder.h @@ -35,6 +35,9 @@ namespace quicktex { class Vector4; +} + +namespace quicktex::s3tc { class BC1Encoder final : public BlockEncoderTemplate { public: @@ -165,10 +168,10 @@ class BC1Encoder final : public BlockEncoderTemplate { // Each entry includes a high and low pair that best reproduces the 8-bit index as well as possible, // with an included error value // these depend on the interpolator - const BC1::MatchListPtr _single_match5 = BC1::SingleColorTable<5, 4>(_interpolator); - const BC1::MatchListPtr _single_match6 = BC1::SingleColorTable<6, 4>(_interpolator); - const BC1::MatchListPtr _single_match5_half = BC1::SingleColorTable<5, 3>(_interpolator); - const BC1::MatchListPtr _single_match6_half = BC1::SingleColorTable<6, 3>(_interpolator); + const MatchListPtr _single_match5 = SingleColorTable<5, 4>(_interpolator); + const MatchListPtr _single_match6 = SingleColorTable<6, 4>(_interpolator); + const MatchListPtr _single_match5_half = SingleColorTable<5, 3>(_interpolator); + const MatchListPtr _single_match6_half = SingleColorTable<6, 3>(_interpolator); Flags _flags; ErrorMode _error_mode; @@ -196,4 +199,4 @@ class BC1Encoder final : public BlockEncoderTemplate { void EndpointSearch(Color4x4 &pixels, EncodeResults &block) const; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc1/Histogram.h b/quicktex/s3tc/bc1/Histogram.h index 61f4e6a..61fcf67 100644 --- a/quicktex/s3tc/bc1/Histogram.h +++ b/quicktex/s3tc/bc1/Histogram.h @@ -30,7 +30,7 @@ #include "../../Vector4.h" #include "../../util.h" -namespace quicktex::BC1 { +namespace quicktex::s3tc { template class Histogram { public: using Hash = uint16_t; @@ -82,4 +82,4 @@ template class Histogram { private: std::array _bins; }; -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/OrderTable.cpp b/quicktex/s3tc/bc1/OrderTable.cpp index 9e7e746..6e41ce5 100644 --- a/quicktex/s3tc/bc1/OrderTable.cpp +++ b/quicktex/s3tc/bc1/OrderTable.cpp @@ -23,7 +23,7 @@ #include "../../Vector4.h" -namespace quicktex::BC1 { +namespace quicktex::s3tc { using Hash = uint16_t; template <> std::atomic OrderTable<3>::generated = false; @@ -324,4 +324,4 @@ const OrderTable<3>::BestOrderArray OrderTable<3>::BestOrders = { template class OrderTable<3>; template class OrderTable<4>; -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/OrderTable.h b/quicktex/s3tc/bc1/OrderTable.h index b23fb35..0ccb05c 100644 --- a/quicktex/s3tc/bc1/OrderTable.h +++ b/quicktex/s3tc/bc1/OrderTable.h @@ -31,7 +31,7 @@ #include "../../Vector4.h" #include "Histogram.h" -namespace quicktex::BC1 { +namespace quicktex::s3tc { template class OrderTable { public: static constexpr unsigned HashCount = 1 << ((N - 1) * 4); // 16**(N-1) @@ -147,4 +147,4 @@ template <> const OrderTable<4>::BestOrderArray OrderTable<4>::BestOrders; extern template class OrderTable<3>; extern template class OrderTable<4>; -} // namespace quicktex::BC1 \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/OrderTable4.cpp b/quicktex/s3tc/bc1/OrderTable4.cpp index 1c285ad..cb2d938 100644 --- a/quicktex/s3tc/bc1/OrderTable4.cpp +++ b/quicktex/s3tc/bc1/OrderTable4.cpp @@ -20,7 +20,7 @@ #include "OrderTable.h" // clang-format off -namespace quicktex::BC1 { +namespace quicktex::s3tc { template <> const OrderTable<4>::BestOrderArray OrderTable<4>::BestOrders = {{ @@ -1966,5 +1966,5 @@ const OrderTable<4>::BestOrderArray OrderTable<4>::BestOrders = {{ { 15,341,13,33,23,77,141,4,0,351,1,260,102,51,82,9,40,349,854,11,115,217,269,137,180,202,922,5,901,22,10,117,21,365,318,197,120,352,64,12,7,153,177,59,291,32,128,2,165,196,372,36,403,317,457,28,18,8,16,304,30,14,450,31,898,37,3,752,48,134,139,494,421,6,453,401,719,90,86,569,523,110,24,55,475,210,49,44,386,17,730,95,247,244,961,143,125,308,342,817,629,98,498,93,96,76,39,275,509,326,99,285,373,57,237,35,402,160,111,253,105,391,221,116,899,72,127,661 } #endif }}; -} // namespace quicktex::BC1 +} // namespace quicktex::s3tc ::BC1 // clang-format on \ No newline at end of file diff --git a/quicktex/s3tc/bc1/SingleColorTable.h b/quicktex/s3tc/bc1/SingleColorTable.h index 57ed876..6da31a1 100644 --- a/quicktex/s3tc/bc1/SingleColorTable.h +++ b/quicktex/s3tc/bc1/SingleColorTable.h @@ -26,7 +26,7 @@ #include "../../util.h" #include "../Interpolator.h" -namespace quicktex::BC1 { +namespace quicktex::s3tc { struct BC1MatchEntry { uint8_t high; @@ -90,4 +90,4 @@ template MatchListPtr SingleColorTable(InterpolatorPtr inte } return matches; } -} // namespace quicktex::BC1 \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc1/__init__.py b/quicktex/s3tc/bc1/__init__.py new file mode 100644 index 0000000..e384cf0 --- /dev/null +++ b/quicktex/s3tc/bc1/__init__.py @@ -0,0 +1 @@ +from _quicktex._s3tc._bc1 import * \ No newline at end of file diff --git a/quicktex/s3tc/bindings/Encoders.cpp b/quicktex/s3tc/bc1/_bindings.cpp similarity index 56% rename from quicktex/s3tc/bindings/Encoders.cpp rename to quicktex/s3tc/bc1/_bindings.cpp index 3852f24..01278e3 100644 --- a/quicktex/s3tc/bindings/Encoders.cpp +++ b/quicktex/s3tc/bc1/_bindings.cpp @@ -19,57 +19,31 @@ #include +#include #include #include #include #include +#include "../../BlockDecoder.h" #include "../../BlockEncoder.h" -#include "../../Color.h" #include "../Interpolator.h" -#include "../bc1/BC1Encoder.h" -#include "../bc3/BC3Encoder.h" -#include "../bc4/BC4Encoder.h" -#include "../bc5/BC5Encoder.h" - -#define STRINGIFY(x) #x -#define MACRO_STRINGIFY(x) STRINGIFY(x) +#include "BC1Decoder.h" +#include "BC1Encoder.h" namespace py = pybind11; namespace quicktex::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"); +using namespace quicktex::s3tc; +using namespace quicktex::s3tc ; - 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(encoded_str.data()), reinterpret_cast(decoded_str.data()), image_width, image_height); - - auto bytes = py::bytes(encoded_str); // encoded data is copied here, unfortunately - - return bytes; -} - -void InitEncoders(py::module_ &m) { - // BlockEncoder - py::class_ 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); +void InitBC1(py::module_ &s3tc) { + auto bc1 = s3tc.def_submodule("_bc1", "BC1 encoding/decoding module"); + auto block_encoder = py::type::of(); + auto block_decoder = py::type::of(); // BC1Encoder - py::class_ bc1_encoder(m, "BC1Encoder", block_encoder); + py::class_ bc1_encoder(bc1, "BC1Encoder", block_encoder); bc1_encoder.def(py::init(), py::arg("interpolator") = Interpolator::Type::Ideal, py::arg("level") = 5, py::arg("use_3color") = true, py::arg("use_3color_black") = true); @@ -112,25 +86,11 @@ void InitEncoders(py::module_ &m) { .value("Check2", BC1Encoder::ErrorMode::Check2) .value("Full", BC1Encoder::ErrorMode::Full); - // BC3Encoder - py::class_ bc3_encoder(m, "BC3Encoder", block_encoder); + // BC1Decoder + py::class_ bc1_decoder(bc1, "BC1Decoder", block_decoder); - bc3_encoder.def(py::init(), py::arg("interpolator") = Interpolator::Type::Ideal, py::arg("level") = 5, - py::arg("use_3color") = true, py::arg("use_3color_black") = true); - bc3_encoder.def_property_readonly("bc1_encoder", &BC3Encoder::GetBC1Encoder); - bc3_encoder.def_property_readonly("bc4_encoder", &BC3Encoder::GetBC4Encoder); - - // BC4Encoder - py::class_ bc4_encoder(m, "BC4Encoder", block_encoder); - - bc4_encoder.def(py::init(), py::arg("channel") = 3); - bc4_encoder.def_property("channel", &BC4Encoder::GetChannel, &BC4Encoder::SetChannel); - - // BC5Encoder - py::class_ bc5_encoder(m, "BC5Encoder", block_encoder); - - bc5_encoder.def(py::init(), py::arg("chan0") = 0, py::arg("chan1") = 1); - bc5_encoder.def_property("channels", &BC5Encoder::GetChannels, &BC5Encoder::SetChannels); - bc5_encoder.def_property_readonly("bc4_decoders", &BC5Encoder::GetBC4Encoders); + bc1_decoder.def(py::init(), py::arg("interpolator") = Interpolator::Type::Ideal, py::arg("write_alpha") = false); + bc1_decoder.def_property_readonly("interpolator_type", &BC1Decoder::GetInterpolatorType); + bc1_decoder.def_readwrite("write_alpha", &BC1Decoder::write_alpha); } } // namespace quicktex::bindings \ No newline at end of file diff --git a/quicktex/s3tc/bc3/BC3Block.h b/quicktex/s3tc/bc3/BC3Block.h index c10d475..6d76fb9 100644 --- a/quicktex/s3tc/bc3/BC3Block.h +++ b/quicktex/s3tc/bc3/BC3Block.h @@ -19,10 +19,10 @@ #pragma once -#include "../../s3tc/bc1/BC1Block.h" -#include "BC4Block.h" +#include "../bc1/BC1Block.h" +#include "../bc4/BC4Block.h" -namespace quicktex { +namespace quicktex::s3tc { #pragma pack(push, 1) class BC3Block { @@ -31,4 +31,4 @@ class BC3Block { BC1Block color_block; }; #pragma pack(pop) -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc3/BC3Decoder.cpp b/quicktex/s3tc/bc3/BC3Decoder.cpp index b6a1ffc..eeaa628 100644 --- a/quicktex/s3tc/bc3/BC3Decoder.cpp +++ b/quicktex/s3tc/bc3/BC3Decoder.cpp @@ -25,10 +25,10 @@ #include "../../ndebug.h" #include "BC3Block.h" -namespace quicktex { +namespace quicktex::s3tc { void BC3Decoder::DecodeBlock(Color4x4 dest, BC3Block *const block) const noexcept(ndebug) { _bc1_decoder->DecodeBlock(dest, &(block->color_block)); _bc4_decoder->DecodeBlock(dest, &(block->alpha_block), 3); } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc3/BC3Decoder.h b/quicktex/s3tc/bc3/BC3Decoder.h index df78638..2e29dad 100644 --- a/quicktex/s3tc/bc3/BC3Decoder.h +++ b/quicktex/s3tc/bc3/BC3Decoder.h @@ -29,7 +29,8 @@ #include "../bc4/BC4Decoder.h" #include "BC3Block.h" -namespace quicktex { +namespace quicktex::s3tc { + class BC3Decoder : public BlockDecoderTemplate { public: using BC1DecoderPtr = std::shared_ptr; @@ -47,4 +48,4 @@ class BC3Decoder : public BlockDecoderTemplate { const BC1DecoderPtr _bc1_decoder; const BC4DecoderPtr _bc4_decoder; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc3/BC3Encoder.cpp b/quicktex/s3tc/bc3/BC3Encoder.cpp index b8aa8f8..8dfd850 100644 --- a/quicktex/s3tc/bc3/BC3Encoder.cpp +++ b/quicktex/s3tc/bc3/BC3Encoder.cpp @@ -22,9 +22,9 @@ #include "../../BlockView.h" #include "BC3Block.h" -namespace quicktex { +namespace quicktex::s3tc { void BC3Encoder::EncodeBlock(Color4x4 pixels, BC3Block *dest) const { _bc1_encoder->EncodeBlock(pixels, &(dest->color_block)); _bc4_encoder->EncodeBlock(pixels, &(dest->alpha_block), 3); } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc3/BC3Encoder.h b/quicktex/s3tc/bc3/BC3Encoder.h index fe53da3..dd14616 100644 --- a/quicktex/s3tc/bc3/BC3Encoder.h +++ b/quicktex/s3tc/bc3/BC3Encoder.h @@ -28,7 +28,7 @@ #include "../bc4/BC4Encoder.h" #include "BC3Block.h" -namespace quicktex { +namespace quicktex::s3tc { class BC3Encoder : public BlockEncoderTemplate { public: @@ -47,4 +47,4 @@ class BC3Encoder : public BlockEncoderTemplate { const BC1EncoderPtr _bc1_encoder; const BC4EncoderPtr _bc4_encoder; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc3/__init__.py b/quicktex/s3tc/bc3/__init__.py new file mode 100644 index 0000000..90a9fe9 --- /dev/null +++ b/quicktex/s3tc/bc3/__init__.py @@ -0,0 +1 @@ +from _quicktex._s3tc._bc3 import * \ No newline at end of file diff --git a/quicktex/s3tc/bc3/_bindings.cpp b/quicktex/s3tc/bc3/_bindings.cpp new file mode 100644 index 0000000..cee2b40 --- /dev/null +++ b/quicktex/s3tc/bc3/_bindings.cpp @@ -0,0 +1,60 @@ +/* Python-rgbcx Texture Compression Library + Copyright (C) 2021 Andrew Cassidy + Partially derived from rgbcx.h written by Richard Geldreich + 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 . + */ + +#include + +#include +#include +#include +#include +#include + +#include "../../BlockDecoder.h" +#include "../../BlockEncoder.h" +#include "../Interpolator.h" +#include "BC3Decoder.h" +#include "BC3Encoder.h" + +namespace py = pybind11; +namespace quicktex::bindings { + +using namespace quicktex::s3tc; +using namespace quicktex::s3tc ; + +void InitBC3(py::module_ &s3tc) { + auto bc3 = s3tc.def_submodule("_bc3", "BC3 encoding/decoding module"); + auto block_encoder = py::type::of(); + auto block_decoder = py::type::of(); + + // BC3Encoder + py::class_ bc3_encoder(bc3, "BC3Encoder", block_encoder); + + bc3_encoder.def(py::init(), py::arg("interpolator") = Interpolator::Type::Ideal, py::arg("level") = 5, + py::arg("use_3color") = true, py::arg("use_3color_black") = true); + bc3_encoder.def_property_readonly("bc1_encoder", &BC3Encoder::GetBC1Encoder); + bc3_encoder.def_property_readonly("bc4_encoder", &BC3Encoder::GetBC4Encoder); + + // BC3Decoder + py::class_ bc3_decoder(bc3, "BC3Decoder", block_decoder); + + bc3_decoder.def(py::init(), py::arg("type") = Interpolator::Type::Ideal); + bc3_decoder.def_property_readonly("bc1_decoder", &BC3Decoder::GetBC1Decoder); + bc3_decoder.def_property_readonly("bc4_decoder", &BC3Decoder::GetBC4Decoder); +}; +} // namespace quicktex::bindings \ No newline at end of file diff --git a/quicktex/s3tc/bc4/BC4Block.h b/quicktex/s3tc/bc4/BC4Block.h index d84dd94..5a8d84d 100644 --- a/quicktex/s3tc/bc4/BC4Block.h +++ b/quicktex/s3tc/bc4/BC4Block.h @@ -28,7 +28,7 @@ #include "../../util.h" #include "../bc1/BC1Block.h" -namespace quicktex { +namespace quicktex::s3tc { #pragma pack(push, 1) class BC4Block { @@ -119,4 +119,4 @@ class BC4Block { std::array selectors; }; #pragma pack(pop) -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc4/BC4Decoder.cpp b/quicktex/s3tc/bc4/BC4Decoder.cpp index 726e56a..538d20d 100644 --- a/quicktex/s3tc/bc4/BC4Decoder.cpp +++ b/quicktex/s3tc/bc4/BC4Decoder.cpp @@ -26,7 +26,8 @@ #include "../../ndebug.h" // for ndebug #include "BC4Block.h" -void quicktex::BC4Decoder::DecodeBlock(Byte4x4 dest, BC4Block *const block) const noexcept(ndebug) { +namespace quicktex::s3tc { +void BC4Decoder::DecodeBlock(Byte4x4 dest, BC4Block *const block) const noexcept(ndebug) { auto l = block->GetLowAlpha(); auto h = block->GetHighAlpha(); @@ -41,3 +42,4 @@ void quicktex::BC4Decoder::DecodeBlock(Byte4x4 dest, BC4Block *const block) cons } } } +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc4/BC4Decoder.h b/quicktex/s3tc/bc4/BC4Decoder.h index 266183d..94c0ce6 100644 --- a/quicktex/s3tc/bc4/BC4Decoder.h +++ b/quicktex/s3tc/bc4/BC4Decoder.h @@ -28,7 +28,7 @@ #include "../../ndebug.h" #include "BC4Block.h" -namespace quicktex { +namespace quicktex::s3tc { class BC4Decoder : public BlockDecoderTemplate { public: BC4Decoder(uint8_t channel = 3) { SetChannel(channel); } @@ -46,4 +46,4 @@ class BC4Decoder : public BlockDecoderTemplate { private: uint8_t _channel; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc4/BC4Encoder.cpp b/quicktex/s3tc/bc4/BC4Encoder.cpp index d4a527a..9c59480 100644 --- a/quicktex/s3tc/bc4/BC4Encoder.cpp +++ b/quicktex/s3tc/bc4/BC4Encoder.cpp @@ -28,7 +28,7 @@ #include "../../ndebug.h" #include "BC4Block.h" -namespace quicktex { +namespace quicktex::s3tc { void BC4Encoder::EncodeBlock(Byte4x4 pixels, BC4Block *const dest) const noexcept(ndebug) { auto flattened = pixels.Flatten(); auto minmax = std::minmax_element(flattened.begin(), flattened.end()); @@ -70,4 +70,4 @@ void BC4Encoder::EncodeBlock(Byte4x4 pixels, BC4Block *const dest) const noexcep dest->PackSelectors(selectors); } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc4/BC4Encoder.h b/quicktex/s3tc/bc4/BC4Encoder.h index 2203570..1b31ecc 100644 --- a/quicktex/s3tc/bc4/BC4Encoder.h +++ b/quicktex/s3tc/bc4/BC4Encoder.h @@ -28,7 +28,7 @@ #include "../../ndebug.h" #include "BC4Block.h" -namespace quicktex { +namespace quicktex::s3tc { class BC4Encoder : public BlockEncoderTemplate { public: @@ -47,4 +47,4 @@ class BC4Encoder : public BlockEncoderTemplate { private: uint8_t _channel; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc4/__init__.py b/quicktex/s3tc/bc4/__init__.py new file mode 100644 index 0000000..70a39de --- /dev/null +++ b/quicktex/s3tc/bc4/__init__.py @@ -0,0 +1 @@ +from _quicktex._s3tc._bc4 import * \ No newline at end of file diff --git a/quicktex/s3tc/bc4/_bindings.cpp b/quicktex/s3tc/bc4/_bindings.cpp new file mode 100644 index 0000000..3181e8b --- /dev/null +++ b/quicktex/s3tc/bc4/_bindings.cpp @@ -0,0 +1,57 @@ +/* Python-rgbcx Texture Compression Library + Copyright (C) 2021 Andrew Cassidy + Partially derived from rgbcx.h written by Richard Geldreich + 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 . + */ + +#include + +#include +#include +#include +#include +#include + +#include "../../BlockDecoder.h" +#include "../../BlockEncoder.h" +#include "BC4Decoder.h" +#include "BC4Encoder.h" + +namespace py = pybind11; +namespace quicktex::bindings { + +using namespace quicktex::s3tc; +using namespace quicktex::s3tc ; + +void InitBC4(py::module_ &s3tc) { + auto bc4 = s3tc.def_submodule("_bc4", "BC4 encoding/decoding module"); + auto block_encoder = py::type::of(); + auto block_decoder = py::type::of(); + + // BC4Encoder + py::class_ bc4_encoder(bc4, "BC4Encoder", block_encoder); + + bc4_encoder.def(py::init(), py::arg("channel") = 3); + bc4_encoder.def_property("channel", &BC4Encoder::GetChannel, &BC4Encoder::SetChannel); + + // BC4Decoder + py::class_ bc4_decoder(bc4, "BC4Decoder", block_decoder); + + bc4_decoder.def(py::init(), py::arg("channel") = 3); + bc4_decoder.def_property("channel", &BC4Decoder::GetChannel, &BC4Decoder::SetChannel); +} + +} // namespace quicktex::bindings \ No newline at end of file diff --git a/quicktex/s3tc/bc5/BC5Block.h b/quicktex/s3tc/bc5/BC5Block.h index 9e088dc..58b7d35 100644 --- a/quicktex/s3tc/bc5/BC5Block.h +++ b/quicktex/s3tc/bc5/BC5Block.h @@ -21,7 +21,7 @@ #include "../bc4/BC4Block.h" -namespace quicktex { +namespace quicktex::s3tc { #pragma pack(push, 1) class BC5Block { @@ -30,4 +30,4 @@ class BC5Block { BC4Block chan1_block; }; #pragma pack(pop) -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc5/BC5Decoder.cpp b/quicktex/s3tc/bc5/BC5Decoder.cpp index 6982d6d..3425870 100644 --- a/quicktex/s3tc/bc5/BC5Decoder.cpp +++ b/quicktex/s3tc/bc5/BC5Decoder.cpp @@ -23,10 +23,10 @@ #include "../../ndebug.h" #include "BC5Block.h" -namespace quicktex { +namespace quicktex::s3tc { void BC5Decoder::DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) { _chan0_decoder->DecodeBlock(dest, &block->chan0_block); _chan1_decoder->DecodeBlock(dest, &block->chan1_block); } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc5/BC5Decoder.h b/quicktex/s3tc/bc5/BC5Decoder.h index 8e2d280..eba620a 100644 --- a/quicktex/s3tc/bc5/BC5Decoder.h +++ b/quicktex/s3tc/bc5/BC5Decoder.h @@ -30,7 +30,8 @@ #include "../bc4/BC4Decoder.h" #include "BC5Block.h" -namespace quicktex { +namespace quicktex::s3tc { + class BC5Decoder : public BlockDecoderTemplate { public: using ChannelPair = std::tuple; @@ -54,4 +55,4 @@ class BC5Decoder : public BlockDecoderTemplate { const BC4DecoderPtr _chan0_decoder; const BC4DecoderPtr _chan1_decoder; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc5/BC5Encoder.cpp b/quicktex/s3tc/bc5/BC5Encoder.cpp index f384b9f..5b8bcdf 100644 --- a/quicktex/s3tc/bc5/BC5Encoder.cpp +++ b/quicktex/s3tc/bc5/BC5Encoder.cpp @@ -19,9 +19,9 @@ #include "BC5Encoder.h" -namespace quicktex { +namespace quicktex::s3tc { void BC5Encoder::EncodeBlock(Color4x4 pixels, BC5Block *dest) const { _chan0_encoder->EncodeBlock(pixels, &(dest->chan0_block)); _chan1_encoder->EncodeBlock(pixels, &(dest->chan1_block)); } -} // namespace quicktex \ No newline at end of file +} // namespace quicktex::s3tc \ No newline at end of file diff --git a/quicktex/s3tc/bc5/BC5Encoder.h b/quicktex/s3tc/bc5/BC5Encoder.h index ad5e228..ebf8a07 100644 --- a/quicktex/s3tc/bc5/BC5Encoder.h +++ b/quicktex/s3tc/bc5/BC5Encoder.h @@ -30,7 +30,8 @@ #include "../bc4/BC4Encoder.h" #include "BC5Block.h" -namespace quicktex { +namespace quicktex::s3tc { + class BC5Encoder : public BlockEncoderTemplate { public: using ChannelPair = std::tuple; @@ -54,4 +55,4 @@ class BC5Encoder : public BlockEncoderTemplate { const BC4EncoderPtr _chan0_encoder; const BC4EncoderPtr _chan1_encoder; }; -} // namespace quicktex +} // namespace quicktex::s3tc diff --git a/quicktex/s3tc/bc5/__init__.py b/quicktex/s3tc/bc5/__init__.py new file mode 100644 index 0000000..64d8a00 --- /dev/null +++ b/quicktex/s3tc/bc5/__init__.py @@ -0,0 +1 @@ +from _quicktex._s3tc._bc5 import * \ No newline at end of file diff --git a/quicktex/s3tc/bc5/_bindings.cpp b/quicktex/s3tc/bc5/_bindings.cpp new file mode 100644 index 0000000..3edcf1b --- /dev/null +++ b/quicktex/s3tc/bc5/_bindings.cpp @@ -0,0 +1,58 @@ +/* Python-rgbcx Texture Compression Library + Copyright (C) 2021 Andrew Cassidy + Partially derived from rgbcx.h written by Richard Geldreich + 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 . + */ + +#include + +#include +#include +#include +#include +#include + +#include "../../BlockDecoder.h" +#include "../../BlockEncoder.h" +#include "BC5Decoder.h" +#include "BC5Encoder.h" + +namespace py = pybind11; +namespace quicktex::bindings { + +using namespace quicktex::s3tc; +using namespace quicktex::s3tc ; + +void InitBC5(py::module_ &s3tc) { + auto bc5 = s3tc.def_submodule("_bc5", "BC5 encoding/decoding module"); + auto block_encoder = py::type::of(); + auto block_decoder = py::type::of(); + + // BC5Encoder + py::class_ bc5_encoder(bc5, "BC5Encoder", block_encoder); + + bc5_encoder.def(py::init(), py::arg("chan0") = 0, py::arg("chan1") = 1); + bc5_encoder.def_property("channels", &BC5Encoder::GetChannels, &BC5Encoder::SetChannels); + bc5_encoder.def_property_readonly("bc4_decoders", &BC5Encoder::GetBC4Encoders); + + // BC5Decoder + py::class_ bc5_decoder(bc5, "BC5Decoder", block_decoder); + + bc5_decoder.def(py::init(), py::arg("chan0") = 0, py::arg("chan1") = 1); + bc5_decoder.def_property("channels", &BC5Decoder::GetChannels, &BC5Decoder::SetChannels); + bc5_decoder.def_property_readonly("bc4_decoders", &BC5Decoder::GetBC4Decoders); +} +} // namespace quicktex::bindings \ No newline at end of file