Compare commits

...

3 Commits

Author SHA1 Message Date
46d64139bd MSVC what the fuck is your problem 2021-03-11 02:29:08 -08:00
ab0d4b30af IWYU pass 2021-03-11 02:18:40 -08:00
b77a5acfb6 Decoder APIs refinement 2021-03-11 02:01:16 -08:00
16 changed files with 65 additions and 49 deletions

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <type_traits>
#include "../BlockDecoder.h" #include "../BlockDecoder.h"
#include "../BlockView.h" #include "../BlockView.h"
@ -32,7 +33,7 @@ class BC1Decoder final : public BlockDecoderTemplate<BC1Block, 4, 4> {
public: public:
using InterpolatorPtr = std::shared_ptr<Interpolator>; using InterpolatorPtr = std::shared_ptr<Interpolator>;
BC1Decoder(Interpolator::Type type = Interpolator::Type::Ideal, bool write_alpha = false) BC1Decoder(Interpolator::Type type = Interpolator::Type::Ideal, bool write_alpha = false)
: _interpolator(Interpolator::MakeInterpolator(type)), write_alpha(write_alpha) {} : write_alpha(write_alpha), _interpolator(Interpolator::MakeInterpolator(type)) {}
void DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcept(ndebug) override; void DecodeBlock(Color4x4 dest, BC1Block *const block) const noexcept(ndebug) override;
@ -40,6 +41,7 @@ class BC1Decoder final : public BlockDecoderTemplate<BC1Block, 4, 4> {
constexpr bool WritesAlpha() const { return write_alpha; } constexpr bool WritesAlpha() const { return write_alpha; }
bool write_alpha; bool write_alpha;
private: private:
const InterpolatorPtr _interpolator; const InterpolatorPtr _interpolator;
}; };

View File

@ -29,6 +29,7 @@
#include "../BlockView.h" #include "../BlockView.h"
#include "../Color.h" #include "../Color.h"
#include "../Interpolator.h"
#include "../Matrix4x4.h" #include "../Matrix4x4.h"
#include "../Vector4.h" #include "../Vector4.h"
#include "../Vector4Int.h" #include "../Vector4Int.h"
@ -45,7 +46,6 @@ using namespace BC1;
BC1Encoder::BC1Encoder(Interpolator::Type type, unsigned int level, bool allow_3color, bool allow_3color_black) BC1Encoder::BC1Encoder(Interpolator::Type type, unsigned int level, bool allow_3color, bool allow_3color_black)
: _interpolator(Interpolator::MakeInterpolator(type)) { : _interpolator(Interpolator::MakeInterpolator(type)) {
OrderTable<3>::Generate(); OrderTable<3>::Generate();
OrderTable<4>::Generate(); OrderTable<4>::Generate();

View File

@ -21,17 +21,19 @@
#include <array> #include <array>
#include <climits> #include <climits>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <type_traits>
#include "../BlockEncoder.h" #include "../BlockEncoder.h"
#include "../BlockView.h" #include "../BlockView.h"
#include "../Color.h" #include "../Color.h"
#include "../Interpolator.h"
#include "BC1Block.h" #include "BC1Block.h"
#include "SingleColorTable.h" #include "SingleColorTable.h"
namespace rgbcx { namespace rgbcx {
class Interpolator;
class Vector4; class Vector4;
class BC1Encoder final : public BlockEncoderTemplate<BC1Block, 4, 4> { class BC1Encoder final : public BlockEncoderTemplate<BC1Block, 4, 4> {

View File

@ -24,7 +24,9 @@
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <mutex>
#include "../Vector4.h" #include "../Vector4.h"
#include "Histogram.h" #include "Histogram.h"

View File

@ -19,8 +19,8 @@
#include "BC3Decoder.h" #include "BC3Decoder.h"
#include "../BC1/BC1Decoder.h" #include <type_traits>
#include "../BC4/BC4Decoder.h"
#include "../BlockView.h" #include "../BlockView.h"
#include "../ndebug.h" #include "../ndebug.h"
#include "BC3Block.h" #include "BC3Block.h"

View File

@ -36,11 +36,14 @@ class BC3Decoder : public BlockDecoderTemplate<BC3Block, 4, 4> {
using BC1DecoderPtr = std::shared_ptr<BC1Decoder>; using BC1DecoderPtr = std::shared_ptr<BC1Decoder>;
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>; using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
BC3Decoder(Interpolator::Type type = Interpolator::Type::Ideal) : BC3Decoder(std::make_shared<BC1Decoder>(type)) {} BC3Decoder(Interpolator::Type type = Interpolator::Type::Ideal) : BC3Decoder(std::make_shared<BC1Decoder>(type), std::make_shared<BC4Decoder>(3)) {}
BC3Decoder(BC1DecoderPtr bc1_decoder, BC4DecoderPtr bc4_decoder = std::make_shared<BC4Decoder>()) : _bc1_decoder(bc1_decoder), _bc4_decoder(bc4_decoder) {} BC3Decoder(BC1DecoderPtr bc1_decoder, BC4DecoderPtr bc4_decoder = std::make_shared<BC4Decoder>()) : _bc1_decoder(bc1_decoder), _bc4_decoder(bc4_decoder) {}
void DecodeBlock(Color4x4 dest, BC3Block *const block) const noexcept(ndebug) override; void DecodeBlock(Color4x4 dest, BC3Block *const block) const noexcept(ndebug) override;
BC1DecoderPtr GetBC1Decoder() const { return _bc1_decoder; }
BC4DecoderPtr GetBC4Decoder() const { return _bc4_decoder; }
private: private:
const BC1DecoderPtr _bc1_decoder; const BC1DecoderPtr _bc1_decoder;
const BC4DecoderPtr _bc4_decoder; const BC4DecoderPtr _bc4_decoder;

View File

@ -19,12 +19,14 @@
#include "BC4Encoder.h" #include "BC4Encoder.h"
#include <algorithm> // for minmax_element #include <algorithm>
#include <array> // for array #include <array>
#include <cstdint> // for uint8_t #include <cstdint>
#include <utility> // for pair #include <utility>
#include "BC4Block.h" // for BC4Block #include "../BlockView.h"
#include "../ndebug.h"
#include "BC4Block.h"
namespace rgbcx { namespace rgbcx {
void BC4Encoder::EncodeBlock(Byte4x4 pixels, BC4Block *const dest) const noexcept(ndebug) { void BC4Encoder::EncodeBlock(Byte4x4 pixels, BC4Block *const dest) const noexcept(ndebug) {

View File

@ -26,7 +26,7 @@
namespace rgbcx { namespace rgbcx {
void BC5Decoder::DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) { void BC5Decoder::DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) {
_bc4_decoder->DecodeBlock(dest, &block->chan0_block, _chan0); _chan0_decoder->DecodeBlock(dest, &block->chan0_block);
_bc4_decoder->DecodeBlock(dest, &block->chan1_block, _chan1); _chan1_decoder->DecodeBlock(dest, &block->chan1_block);
} }
} // namespace rgbcx } // namespace rgbcx

View File

@ -19,11 +19,10 @@
#pragma once #pragma once
#include <cassert>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <tuple>
#include <memory> #include <memory>
#include <tuple>
#include <type_traits>
#include "../BC4/BC4Decoder.h" #include "../BC4/BC4Decoder.h"
#include "../BlockDecoder.h" #include "../BlockDecoder.h"
@ -36,31 +35,23 @@ class BC5Decoder : public BlockDecoderTemplate<BC5Block, 4, 4> {
public: public:
using ChannelPair = std::tuple<uint8_t, uint8_t>; using ChannelPair = std::tuple<uint8_t, uint8_t>;
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>; using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
using BC4DecoderPair = std::tuple<BC4DecoderPtr, BC4DecoderPtr>;
BC5Decoder(uint8_t chan0 = 0, uint8_t chan1 = 1) : BC5Decoder(std::make_shared<BC4Decoder>(), chan0, chan1) {} BC5Decoder(uint8_t chan0 = 0, uint8_t chan1 = 1) : BC5Decoder(std::make_shared<BC4Decoder>(chan0), std::make_shared<BC4Decoder>(chan1)) {}
BC5Decoder(BC4DecoderPtr bc4_decoder, uint8_t chan0 = 0, uint8_t chan1 = 1) : _bc4_decoder(bc4_decoder), _chan0(chan0), _chan1(chan1) { BC5Decoder(BC4DecoderPtr chan0_decoder, BC4DecoderPtr chan1_decoder) : _chan0_decoder(chan0_decoder), _chan1_decoder(chan1_decoder) {}
assert(chan0 < 4U);
assert(chan1 < 4U);
assert(chan0 != chan1);
}
void DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) override; void DecodeBlock(Color4x4 dest, BC5Block *const block) const noexcept(ndebug) override;
constexpr size_t GetChannel0() const { return _chan0; } ChannelPair GetChannels() const { return ChannelPair(_chan0_decoder->GetChannel(), _chan1_decoder->GetChannel()); }
constexpr size_t GetChannel1() const { return _chan1; }
ChannelPair GetChannels() const { return ChannelPair(_chan0, _chan1); }
void SetChannels(ChannelPair channels) { void SetChannels(ChannelPair channels) {
if (std::get<0>(channels) >= 4) throw std::invalid_argument("Channel 0 out of range"); _chan0_decoder->SetChannel(std::get<0>(channels));
if (std::get<1>(channels) >= 4) throw std::invalid_argument("Channel 1 out of range"); _chan1_decoder->SetChannel(std::get<1>(channels));
_chan0 = std::get<0>(channels);
_chan1 = std::get<1>(channels);
} }
BC4DecoderPair GetBC4Decoders() const { return BC4DecoderPair(_chan0_decoder, _chan1_decoder); }
private: private:
const BC4DecoderPtr _bc4_decoder; const BC4DecoderPtr _chan0_decoder;
uint8_t _chan0; const BC4DecoderPtr _chan1_decoder;
uint8_t _chan1;
}; };
} // namespace rgbcx } // namespace rgbcx

View File

@ -23,6 +23,7 @@
#include <cstdint> #include <cstdint>
#include <span> #include <span>
#include <vector> #include <vector>
#include <memory>
#include "BlockView.h" #include "BlockView.h"
#include "ndebug.h" #include "ndebug.h"
@ -75,7 +76,7 @@ class BlockDecoderTemplate : public BlockDecoder {
assert(pixel_x + N <= image_width); assert(pixel_x + N <= image_width);
unsigned top_left = pixel_x + (pixel_y * image_width); unsigned top_left = pixel_x + (pixel_y * image_width);
auto dest = DecodedBlock(&decoded[top_left], image_width); auto dest = DecodedBlock(&decoded[top_left], (int)image_width);
DecodeBlock(dest, &blocks[x + block_width * y]); DecodeBlock(dest, &blocks[x + block_width * y]);
} }

View File

@ -55,7 +55,6 @@ template <class B, size_t M, size_t N> class BlockEncoderTemplate : public Block
unsigned block_width = image_width / N; unsigned block_width = image_width / N;
unsigned block_height = image_height / M; unsigned block_height = image_height / M;
unsigned block_count = block_width * block_height;
auto blocks = reinterpret_cast<B *>(encoded); auto blocks = reinterpret_cast<B *>(encoded);
@ -64,11 +63,11 @@ template <class B, size_t M, size_t N> class BlockEncoderTemplate : public Block
// As a result, this is sometimes left as a serial operation despite being embarassingly parallelizable // As a result, this is sometimes left as a serial operation despite being embarassingly parallelizable
// threshold for number of blocks before multithreading is set by overriding MTThreshold() // threshold for number of blocks before multithreading is set by overriding MTThreshold()
#pragma omp parallel for if (block_count >= MTThreshold()) #pragma omp parallel for if (block_width * block_height >= MTThreshold())
for (unsigned y = 0; y < block_height; y++) { for (int y = 0; y < (int)block_height; y++) {
for (unsigned x = 0; x < block_width; x++) { for (int x = 0; x < (int)block_width; x++) {
unsigned pixel_x = x * N; unsigned pixel_x = (unsigned)x * N;
unsigned pixel_y = y * M; unsigned pixel_y = (unsigned)y * M;
assert(pixel_x >= 0); assert(pixel_x >= 0);
assert(pixel_y >= 0); assert(pixel_y >= 0);
@ -76,9 +75,10 @@ template <class B, size_t M, size_t N> class BlockEncoderTemplate : public Block
assert(pixel_x + N <= image_width); assert(pixel_x + N <= image_width);
unsigned top_left = pixel_x + (pixel_y * image_width); unsigned top_left = pixel_x + (pixel_y * image_width);
unsigned block_index = (unsigned)x + (block_width * (unsigned)y);
auto src = DecodedBlock(&decoded[top_left], (int)image_width); auto src = DecodedBlock(&decoded[top_left], (int)image_width);
EncodeBlock(src, &blocks[x + block_width * y]); EncodeBlock(src, &blocks[block_index]);
} }
} }
} }

View File

@ -30,7 +30,7 @@ Color::Color() { SetRGBA(0, 0, 0, 0xFF); }
Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { SetRGBA(r, g, b, a); } Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { SetRGBA(r, g, b, a); }
Color::Color(Vector4Int v) { SetRGBA(v[0], v[1], v[2], v[3]); } Color::Color(Vector4Int v) { SetRGBA((uint8_t)v[0], (uint8_t)v[1], (uint8_t)v[2], (uint8_t)v[3]); }
uint16_t Color::Pack565Unscaled(uint8_t r, uint8_t g, uint8_t b) { uint16_t Color::Pack565Unscaled(uint8_t r, uint8_t g, uint8_t b) {
assert5bit(r); assert5bit(r);

View File

@ -20,6 +20,8 @@
#pragma once #pragma once
#include <array> #include <array>
#include <cassert>
#include <cstddef>
#include <functional> #include <functional>
#include "Vector4.h" #include "Vector4.h"

View File

@ -19,17 +19,17 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <cstddef>
#include <cstdint>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <array>
#include "../BC1/BC1Decoder.h" #include "../BC1/BC1Decoder.h"
#include "../BC3/BC3Decoder.h" #include "../BC3/BC3Decoder.h"
#include "../BC4/BC4Decoder.h" #include "../BC4/BC4Decoder.h"
#include "../BC5/BC5Decoder.h" #include "../BC5/BC5Decoder.h"
#include "../BlockDecoder.h" #include "../BlockDecoder.h"
#include "../bitwiseEnums.h"
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
namespace py = pybind11; namespace py = pybind11;
namespace rgbcx::bindings { namespace rgbcx::bindings {
@ -46,7 +46,7 @@ py::bytes DecodeImage(const BlockDecoder &self, py::bytes encoded, unsigned imag
std::string encoded_str = (std::string)encoded; // encoded data is copied here, unfortunately std::string encoded_str = (std::string)encoded; // encoded data is copied here, unfortunately
std::string decoded_str = std::string(color_size, 0); std::string decoded_str = std::string(color_size, 0);
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"); if (encoded_str.size() != block_size) throw std::invalid_argument("Incompatible data: image width and height do not match the size of the encoded image");
self.DecodeImage(reinterpret_cast<uint8_t *>(encoded_str.data()), reinterpret_cast<Color *>(decoded_str.data()), image_width, image_height); self.DecodeImage(reinterpret_cast<uint8_t *>(encoded_str.data()), reinterpret_cast<Color *>(decoded_str.data()), image_width, image_height);
@ -74,7 +74,9 @@ void InitDecoders(py::module_ &m) {
// BC3Decoder // BC3Decoder
py::class_<BC3Decoder> bc3_decoder(m, "BC3Decoder", block_decoder); py::class_<BC3Decoder> bc3_decoder(m, "BC3Decoder", block_decoder);
bc3_decoder.def(py::init<Interpolator::Type>(), py::arg("interpolator") = Interpolator::Type::Ideal); bc3_decoder.def(py::init<Interpolator::Type>(), 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 // BC4Decoder
py::class_<BC4Decoder> bc4_decoder(m, "BC4Decoder", block_decoder); py::class_<BC4Decoder> bc4_decoder(m, "BC4Decoder", block_decoder);
@ -87,6 +89,7 @@ void InitDecoders(py::module_ &m) {
bc5_decoder.def(py::init<uint8_t, uint8_t>(), py::arg("chan0") = 0, py::arg("chan1") = 1); bc5_decoder.def(py::init<uint8_t, uint8_t>(), py::arg("chan0") = 0, py::arg("chan1") = 1);
bc5_decoder.def_property("channels", &BC5Decoder::GetChannels, &BC5Decoder::SetChannels); bc5_decoder.def_property("channels", &BC5Decoder::GetChannels, &BC5Decoder::SetChannels);
bc5_decoder.def_property_readonly("bc4_decoders", &BC5Decoder::GetBC4Decoders);
} }
} // namespace rgbcx::bindings } // namespace rgbcx::bindings

View File

@ -19,11 +19,15 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <cstddef>
#include <cstdint>
#include <stdexcept> #include <stdexcept>
#include <string>
#include "../BC1/BC1Encoder.h" #include "../BC1/BC1Encoder.h"
#include "../BlockEncoder.h" #include "../BlockEncoder.h"
#include "../bitwiseEnums.h" #include "../Color.h"
#include "../Interpolator.h"
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)

View File

@ -20,6 +20,10 @@
// This file allows for easy debugging in CLion or other IDEs that dont natively support cross-debugging between Python and C++ // 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 <pybind11/embed.h>
#include <array>
#include <string>
namespace py = pybind11; namespace py = pybind11;
#define STRINGIFY(x) #x #define STRINGIFY(x) #x