mirror of
https://github.com/drewcassidy/quicktex.git
synced 2024-09-13 06:37:34 +00:00
Reorganize and add Window class
This commit is contained in:
parent
f88212af85
commit
6f075b6c1d
@ -19,6 +19,7 @@ file(GLOB SOURCE_FILES
|
||||
"quicktex/*.cpp"
|
||||
"quicktex/util/*.cpp"
|
||||
"quicktex/ctests/*.cpp"
|
||||
"quicktex/texture/*.cpp"
|
||||
"quicktex/s3tc/*.cpp"
|
||||
"quicktex/s3tc/bc1/*.cpp"
|
||||
"quicktex/s3tc/bc3/*.cpp"
|
||||
@ -31,6 +32,7 @@ file(GLOB HEADER_FILES
|
||||
"quicktex/*.h"
|
||||
"quicktex/util/*.h"
|
||||
"quicktex/ctests/*.h"
|
||||
"quicktex/texture/*.h"
|
||||
"quicktex/s3tc/*.h"
|
||||
"quicktex/s3tc/bc1/*.h"
|
||||
"quicktex/s3tc/bc3/*.h"
|
||||
|
@ -19,9 +19,12 @@
|
||||
|
||||
#pragma once
|
||||
#include "Vec.h"
|
||||
#include "bitbash.h"
|
||||
#include "util/bitbash.h"
|
||||
|
||||
namespace quicktex::color {
|
||||
namespace quicktex {
|
||||
|
||||
using Color = Vec<uint8_t, 4>;
|
||||
using ColorRGB = Vec<uint8_t, 3>;
|
||||
|
||||
constexpr size_t uint5_max = (1 << 5) - 1;
|
||||
constexpr size_t uint6_max = (1 << 6) - 1;
|
||||
@ -71,4 +74,4 @@ template <typename T = int16_t> Vec<T, 3> precise_round_565(Vec<float, 3> &v) {
|
||||
|
||||
return rounded;
|
||||
}
|
||||
} // namespace quicktex::color
|
||||
} // namespace quicktex
|
@ -22,7 +22,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Texture.h"
|
||||
#include "texture/RawTexture.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
@ -46,19 +46,19 @@ template <class T> class BlockDecoder : public Decoder<T> {
|
||||
virtual DecodedBlock DecodeBlock(const EncodedBlock &block) const = 0;
|
||||
|
||||
virtual RawTexture Decode(const T &encoded) const override {
|
||||
auto decoded = RawTexture(encoded.Width(), encoded.Height());
|
||||
auto decoded = RawTexture(encoded.width, encoded.height);
|
||||
|
||||
int blocks_x = encoded.BlocksX();
|
||||
int blocks_y = encoded.BlocksY();
|
||||
int blocks_x = encoded.bwidth();
|
||||
int blocks_y = encoded.bheight();
|
||||
|
||||
// from experimentation, multithreading this using OpenMP actually makes decoding slower
|
||||
// due to thread creation/teardown taking longer than the decoding process itself.
|
||||
// As a result, this is left as a serial operation despite being embarassingly parallelizable
|
||||
for (int y = 0; y < blocks_y; y++) {
|
||||
for (int x = 0; x < blocks_x; x++) {
|
||||
auto block = encoded.GetBlock(x, y);
|
||||
auto block = encoded.get_block(x, y);
|
||||
auto pixels = DecodeBlock(block);
|
||||
decoded.SetBlock<BlockWidth, BlockHeight>(x, y, pixels);
|
||||
decoded.set_block<BlockWidth, BlockHeight>(x, y, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Texture.h"
|
||||
#include "texture/RawTexture.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
@ -46,10 +46,10 @@ template <typename T> class BlockEncoder : public Encoder<T> {
|
||||
virtual EncodedBlock EncodeBlock(const DecodedBlock &block) const = 0;
|
||||
|
||||
virtual T Encode(const RawTexture &decoded) const override {
|
||||
auto encoded = T(decoded.Width(), decoded.Height());
|
||||
auto encoded = T(decoded.width, decoded.height);
|
||||
|
||||
int blocks_x = encoded.BlocksX();
|
||||
int blocks_y = encoded.BlocksY();
|
||||
int blocks_x = encoded.bwidth();
|
||||
int blocks_y = encoded.bheight();
|
||||
|
||||
// from experimentation, multithreading this using OpenMP sometimes actually makes encoding slower
|
||||
// due to thread creation/teardown taking longer than the encoding process itself.
|
||||
@ -58,9 +58,9 @@ template <typename T> class BlockEncoder : public Encoder<T> {
|
||||
#pragma omp parallel for if (blocks_x * blocks_y >= MTThreshold())
|
||||
for (int y = 0; y < blocks_y; y++) {
|
||||
for (int x = 0; x < blocks_x; x++) {
|
||||
auto pixels = decoded.GetBlock<BlockWidth, BlockHeight>(x, y);
|
||||
auto pixels = decoded.get_block<BlockWidth, BlockHeight>(x, y);
|
||||
auto block = EncodeBlock(pixels);
|
||||
encoded.SetBlock(x, y, block);
|
||||
encoded.set_block(x, y, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
OldColor::OldColor(Vector4Int v) {
|
||||
if (v.MaxAbs() > 0xFF) throw std::invalid_argument("Vector members out of range");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdint> // for uint8_t, uint16_t
|
||||
|
||||
#include "Vec.h"
|
||||
|
||||
namespace quicktex {
|
||||
class Vector4;
|
||||
class Vector4Int;
|
||||
@ -84,16 +86,29 @@ class OldColor {
|
||||
|
||||
int GetLuma() const { return (13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U; } // REC709 weightings
|
||||
|
||||
operator Vec<uint8_t, 4>() const { return {r, g, b, a}; }
|
||||
|
||||
OldColor(const Vec<uint8_t, 4> v) {
|
||||
r = v.r();
|
||||
g = v.g();
|
||||
b = v.b();
|
||||
a = v.a();
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr float Midpoints5bit[32] = {.015686f, .047059f, .078431f, .111765f, .145098f, .176471f, .207843f, .241176f, .274510f, .305882f, .337255f,
|
||||
.370588f, .403922f, .435294f, .466667f, .5f, .533333f, .564706f, .596078f, .629412f, .662745f, .694118f,
|
||||
.725490f, .758824f, .792157f, .823529f, .854902f, .888235f, .921569f, .952941f, .984314f, 1e+37f};
|
||||
static constexpr float Midpoints6bit[64] = {.007843f, .023529f, .039216f, .054902f, .070588f, .086275f, .101961f, .117647f, .133333f, .149020f, .164706f,
|
||||
.180392f, .196078f, .211765f, .227451f, .245098f, .262745f, .278431f, .294118f, .309804f, .325490f, .341176f,
|
||||
.356863f, .372549f, .388235f, .403922f, .419608f, .435294f, .450980f, .466667f, .482353f, .500000f, .517647f,
|
||||
.533333f, .549020f, .564706f, .580392f, .596078f, .611765f, .627451f, .643137f, .658824f, .674510f, .690196f,
|
||||
.705882f, .721569f, .737255f, .754902f, .772549f, .788235f, .803922f, .819608f, .835294f, .850980f, .866667f,
|
||||
.882353f, .898039f, .913725f, .929412f, .945098f, .960784f, .976471f, .992157f, 1e+37f};
|
||||
static constexpr float Midpoints5bit[32] = {
|
||||
.015686f, .047059f, .078431f, .111765f, .145098f, .176471f, .207843f, .241176f, .274510f, .305882f, .337255f,
|
||||
.370588f, .403922f, .435294f, .466667f, .5f, .533333f, .564706f, .596078f, .629412f, .662745f, .694118f,
|
||||
.725490f, .758824f, .792157f, .823529f, .854902f, .888235f, .921569f, .952941f, .984314f, 1e+37f};
|
||||
static constexpr float Midpoints6bit[64] = {
|
||||
.007843f, .023529f, .039216f, .054902f, .070588f, .086275f, .101961f, .117647f, .133333f, .149020f, .164706f,
|
||||
.180392f, .196078f, .211765f, .227451f, .245098f, .262745f, .278431f, .294118f, .309804f, .325490f, .341176f,
|
||||
.356863f, .372549f, .388235f, .403922f, .419608f, .435294f, .450980f, .466667f, .482353f, .500000f, .517647f,
|
||||
.533333f, .549020f, .564706f, .580392f, .596078f, .611765f, .627451f, .643137f, .658824f, .674510f, .690196f,
|
||||
.705882f, .721569f, .737255f, .754902f, .772549f, .788235f, .803922f, .819608f, .835294f, .850980f, .866667f,
|
||||
.882353f, .898039f, .913725f, .929412f, .945098f, .960784f, .976471f, .992157f, 1e+37f};
|
||||
|
||||
|
||||
};
|
||||
#pragma pack(pop)
|
||||
} // namespace quicktex
|
@ -1,187 +0,0 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
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
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "OldColor.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
virtual ~Texture() = default;
|
||||
|
||||
virtual int Width() const { return _width; }
|
||||
virtual int Height() const { return _height; }
|
||||
virtual std::tuple<int, int> Size() const { return std::tuple<int, int>(_width, _height); }
|
||||
|
||||
/**
|
||||
* The texture's total size
|
||||
* @return The size of the texture in bytes.
|
||||
*/
|
||||
virtual size_t NBytes() const noexcept = 0;
|
||||
|
||||
virtual const uint8_t *Data() const noexcept = 0;
|
||||
virtual uint8_t *Data() noexcept = 0;
|
||||
|
||||
protected:
|
||||
Texture(int width, int height) : _width(width), _height(height) {
|
||||
if (width <= 0) throw std::invalid_argument("Texture width must be greater than 0");
|
||||
if (height <= 0) throw std::invalid_argument("Texture height must be greater than 0");
|
||||
}
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
class RawTexture : public Texture {
|
||||
using Base = Texture;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new RawTexture
|
||||
* @param width width of the texture in pixels
|
||||
* @param height height of the texture in pixels
|
||||
*/
|
||||
RawTexture(int width, int height) : Base(width, height), _pixels(_width * _height) {}
|
||||
|
||||
OldColor GetPixel(int x, int y) const {
|
||||
if (x < 0 || x >= _width) throw std::invalid_argument("x value out of range.");
|
||||
if (y < 0 || y >= _height) throw std::invalid_argument("y value out of range.");
|
||||
return _pixels.at(x + (y * _width));
|
||||
}
|
||||
|
||||
void SetPixel(int x, int y, OldColor val) {
|
||||
if (x < 0 || x >= _width) throw std::invalid_argument("x value out of range.");
|
||||
if (y < 0 || y >= _height) throw std::invalid_argument("y value out of range.");
|
||||
_pixels.at(x + (y * _width)) = val;
|
||||
}
|
||||
|
||||
size_t NBytes() const noexcept override { return static_cast<unsigned long>(Width() * Height()) * sizeof(OldColor); }
|
||||
|
||||
template <int N, int M> ColorBlock<N, M> GetBlock(int block_x, int block_y) const {
|
||||
if (block_x < 0) throw std::out_of_range("x value out of range.");
|
||||
if (block_y < 0) throw std::out_of_range("y value out of range.");
|
||||
|
||||
// coordinates in the image of the top-left pixel of the selected block
|
||||
ColorBlock<N, M> block;
|
||||
int pixel_x = block_x * N;
|
||||
int pixel_y = block_y * M;
|
||||
|
||||
if (pixel_x + N < _width && pixel_y + M < _height) {
|
||||
// fast memcpy if the block is entirely inside the bounds of the texture
|
||||
for (int y = 0; y < M; y++) {
|
||||
// copy each row into the ColorBlock
|
||||
block.SetRow(y, &_pixels[pixel_x + (_width * (pixel_y + y))]);
|
||||
}
|
||||
} else {
|
||||
// slower pixel-wise copy if the block goes over the edges
|
||||
for (int x = 0; x < N; x++) {
|
||||
for (int y = 0; y < M; y++) { block.Set(x, y, GetPixel((pixel_x + x) % _width, (pixel_y + y) % _height)); }
|
||||
}
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
template <int N, int M> void SetBlock(int block_x, int block_y, const ColorBlock<N, M> &block) {
|
||||
if (block_x < 0) throw std::out_of_range("x value out of range.");
|
||||
if (block_y < 0) throw std::out_of_range("y value out of range.");
|
||||
|
||||
// coordinates in the image of the top-left pixel of the selected block
|
||||
int pixel_x = block_x * N;
|
||||
int pixel_y = block_y * M;
|
||||
|
||||
if (pixel_x + N < _width && pixel_y + M < _height) {
|
||||
// fast row-wise memcpy if the block is entirely inside the bounds of the texture
|
||||
for (int y = 0; y < M; y++) {
|
||||
// copy each row out of the ColorBlock
|
||||
block.GetRow(y, &_pixels[pixel_x + (_width * (pixel_y + y))]);
|
||||
}
|
||||
} else {
|
||||
// slower pixel-wise copy if the block goes over the edges
|
||||
for (int x = 0; x < N; x++) {
|
||||
for (int y = 0; y < M; y++) { SetPixel((pixel_x + x) % _width, (pixel_y + y) % _height, block.Get(x, y)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual const uint8_t *Data() const noexcept override { return reinterpret_cast<const uint8_t *>(_pixels.data()); }
|
||||
virtual uint8_t *Data() noexcept override { return reinterpret_cast<uint8_t *>(_pixels.data()); }
|
||||
|
||||
protected:
|
||||
std::vector<OldColor> _pixels;
|
||||
};
|
||||
|
||||
template <typename B> class BlockTexture final : public Texture {
|
||||
private:
|
||||
std::vector<B> _blocks;
|
||||
int _width_b;
|
||||
int _height_b;
|
||||
|
||||
public:
|
||||
using BlockType = B;
|
||||
using Base = Texture;
|
||||
|
||||
/**
|
||||
* Create a new BlockTexture
|
||||
* @param width width of the texture in pixels. must be divisible by B::Width
|
||||
* @param height height of the texture in pixels. must be divisible by B::Height
|
||||
*/
|
||||
BlockTexture(int width, int height) : Base(width, height) {
|
||||
_width_b = (_width + B::Width - 1) / B::Width;
|
||||
_height_b = (_height + B::Height - 1) / B::Height;
|
||||
_blocks = std::vector<B>(_width_b * _height_b);
|
||||
}
|
||||
|
||||
constexpr int BlocksX() const { return _width_b; }
|
||||
constexpr int BlocksY() const { return _height_b; }
|
||||
constexpr std::tuple<int, int> BlocksXY() const { return std::tuple<int, int>(_width_b, _height_b); }
|
||||
|
||||
B GetBlock(int x, int y) const {
|
||||
if (x < 0 || x >= _width_b) throw std::out_of_range("x value out of range.");
|
||||
if (y < 0 || y >= _height_b) throw std::out_of_range("y value out of range.");
|
||||
return _blocks.at(x + (y * _width_b));
|
||||
}
|
||||
|
||||
void SetBlock(int x, int y, const B &val) {
|
||||
if (x < 0 || x >= _width_b) throw std::out_of_range("x value out of range.");
|
||||
if (y < 0 || y >= _height_b) throw std::out_of_range("y value out of range.");
|
||||
_blocks.at(x + (y * _width_b)) = val;
|
||||
}
|
||||
|
||||
size_t NBytes() const noexcept override { return _blocks.size() * sizeof(B); }
|
||||
|
||||
const uint8_t *Data() const noexcept override { return reinterpret_cast<const uint8_t *>(_blocks.data()); }
|
||||
uint8_t *Data() noexcept override { return reinterpret_cast<uint8_t *>(_blocks.data()); }
|
||||
};
|
||||
|
||||
} // namespace quicktex
|
@ -117,24 +117,24 @@ template <typename T, size_t N> class Vec {
|
||||
|
||||
// region accessor shortcuts
|
||||
// RGBA accessors
|
||||
std::enable_if<N >= 1, T> r() const { return _c[0]; }
|
||||
std::enable_if<N >= 1, T &> r() { return _c[0]; }
|
||||
std::enable_if<N >= 2, T> g() const { return _c[1]; }
|
||||
std::enable_if<N >= 2, T &> g() { return _c[1]; }
|
||||
std::enable_if<N >= 3, T> b() const { return _c[2]; }
|
||||
std::enable_if<N >= 3, T &> b() { return _c[2]; }
|
||||
std::enable_if<N >= 4, T> a() const { return _c[3]; }
|
||||
std::enable_if<N >= 4, T &> a() { return _c[3]; }
|
||||
T r() const { return _c[0]; }
|
||||
T &r() { return _c[0]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 2, S> g() const { return _c[1]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 2, S &> g() { return _c[1]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 3, S> b() const { return _c[2]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 3, S &> b() { return _c[2]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 4, S> a() const { return _c[3]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 4, S &> a() { return _c[3]; }
|
||||
|
||||
// XYZW accessors
|
||||
std::enable_if<N >= 1, T> x() const { return _c[0]; }
|
||||
std::enable_if<N >= 1, T &> x() { return _c[0]; }
|
||||
std::enable_if<N >= 2, T> y() const { return _c[1]; }
|
||||
std::enable_if<N >= 2, T &> y() { return _c[1]; }
|
||||
std::enable_if<N >= 3, T> z() const { return _c[2]; }
|
||||
std::enable_if<N >= 3, T &> z() { return _c[2]; }
|
||||
std::enable_if<N >= 4, T> w() const { return _c[3]; }
|
||||
std::enable_if<N >= 4, T &> w() { return _c[3]; }
|
||||
T x() const { return _c[0]; }
|
||||
T &x() { return _c[0]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 2, S> y() const { return _c[1]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 2, S &> y() { return _c[1]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 3, S> z() const { return _c[2]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 3, S &> z() { return _c[2]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 4, S> w() const { return _c[3]; }
|
||||
template <typename S = T> std::enable_if_t<N >= 4, S &> w() { return _c[3]; }
|
||||
// endregion
|
||||
|
||||
// region simple operators
|
||||
|
@ -25,8 +25,9 @@
|
||||
#include "Decoder.h"
|
||||
#include "Encoder.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "_bindings.h"
|
||||
#include "texture/RawTexture.h"
|
||||
#include "texture/Texture.h"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define MACRO_STRINGIFY(x) STRINGIFY(x)
|
||||
@ -60,14 +61,14 @@ PYBIND11_MODULE(_quicktex, m) {
|
||||
|
||||
py::class_<Texture> texture(m, "Texture", py::buffer_protocol());
|
||||
|
||||
texture.def_property_readonly("nbytes", &Texture::NBytes);
|
||||
texture.def_property_readonly("nbytes", &Texture::nbytes);
|
||||
texture.def_property_readonly("size", &Texture::Size);
|
||||
texture.def_property_readonly("width", &Texture::Width);
|
||||
texture.def_property_readonly("height", &Texture::Height);
|
||||
texture.def_readonly("width", &Texture::width);
|
||||
texture.def_readonly("height", &Texture::height);
|
||||
|
||||
texture.def_buffer([](Texture &t) { return py::buffer_info(t.Data(), t.NBytes()); });
|
||||
texture.def_buffer([](Texture &t) { return py::buffer_info(t.data(), t.nbytes()); });
|
||||
texture.def("tobytes",
|
||||
[](const Texture &t) { return py::bytes(reinterpret_cast<const char *>(t.Data()), t.NBytes()); });
|
||||
[](const Texture &t) { return py::bytes(reinterpret_cast<const char *>(t.data()), t.nbytes()); });
|
||||
|
||||
// RawTexture
|
||||
|
||||
@ -76,7 +77,9 @@ PYBIND11_MODULE(_quicktex, m) {
|
||||
raw_texture.def(py::init<int, int>(), "width"_a, "height"_a);
|
||||
raw_texture.def_static("frombytes", &BufferToTexture<RawTexture>, "data"_a, "width"_a, "height"_a);
|
||||
|
||||
DefSubscript2D(raw_texture, &RawTexture::GetPixel, &RawTexture::SetPixel, &RawTexture::Size);
|
||||
DefSubscript2DRef(
|
||||
raw_texture, [](RawTexture &self, int x, int y) -> Color { return self.pixel(x, y); },
|
||||
[](RawTexture &self, int x, int y, Color val) { self.pixel(x, y) = val; }, &RawTexture::Size);
|
||||
|
||||
InitS3TC(m);
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace pybind11::detail {
|
||||
@ -83,6 +83,52 @@ template <> struct type_caster<OldColor> {
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct type_caster<Color> {
|
||||
public:
|
||||
PYBIND11_TYPE_CASTER(Color, _("Color"));
|
||||
|
||||
bool load(handle src, bool) {
|
||||
PyObject* source = src.ptr();
|
||||
|
||||
PyObject* tmp = PySequence_Tuple(source);
|
||||
|
||||
// if the object is not a tuple, return false
|
||||
if (!tmp) { return false; } // incorrect type
|
||||
|
||||
// check the size
|
||||
Py_ssize_t size = PyTuple_Size(tmp);
|
||||
if (size < 3 || size > 4) { return false; } // incorrect size
|
||||
|
||||
value.a() = 0xFF;
|
||||
// now we get the contents
|
||||
for (int i = 0; i < size; i++) {
|
||||
PyObject* src_chan = PyTuple_GetItem(tmp, i);
|
||||
PyObject* tmp_chan = PyNumber_Long(src_chan);
|
||||
|
||||
if (!tmp_chan) return false; // incorrect channel type
|
||||
|
||||
auto chan = PyLong_AsLong(tmp_chan);
|
||||
if (chan > 0xFF || chan < 0) return false; // item out of range
|
||||
value[static_cast<unsigned>(i)] = static_cast<uint8_t>(chan);
|
||||
Py_DECREF(tmp_chan);
|
||||
}
|
||||
Py_DECREF(tmp);
|
||||
|
||||
return !PyErr_Occurred();
|
||||
}
|
||||
|
||||
static handle cast(Color src, return_value_policy, handle) {
|
||||
PyObject* val = PyTuple_New(4);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PyObject* chan = PyLong_FromLong(src[static_cast<unsigned>(i)]);
|
||||
PyTuple_SetItem(val, i, chan);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
};
|
||||
} // namespace pybind11::detail
|
||||
|
||||
namespace py = pybind11;
|
||||
@ -114,7 +160,7 @@ template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
|
||||
|
||||
auto info = buf.request(false);
|
||||
auto output = T(width, height);
|
||||
auto dst_size = output.NBytes();
|
||||
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.");
|
||||
@ -129,7 +175,7 @@ template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
|
||||
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");
|
||||
}
|
||||
|
||||
std::memcpy(output.Data(), info.ptr, dst_size);
|
||||
std::memcpy(output.data(), info.ptr, dst_size);
|
||||
|
||||
return output;
|
||||
}
|
||||
@ -197,6 +243,32 @@ void DefSubscript2D(Tpy t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
"key"_a, "value"_a);
|
||||
}
|
||||
|
||||
// TODO: untangle this mess
|
||||
template <typename Tpy, typename Getter, typename Setter, typename Extent>
|
||||
void DefSubscript2DRef(Tpy t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
using T = typename Tpy::type;
|
||||
using V = typename std::remove_cvref_t<std::invoke_result_t<Getter, T&, int, int>>;
|
||||
using Coords = std::tuple<int, int>;
|
||||
t.def(
|
||||
"__getitem__",
|
||||
[get, ext](T& self, Coords pnt) {
|
||||
Coords s = (self.*ext)();
|
||||
int x = PyIndex(std::get<0>(pnt), std::get<0>(s), "x");
|
||||
int y = PyIndex(std::get<1>(pnt), std::get<1>(s), "y");
|
||||
return get(self, x, y);
|
||||
},
|
||||
"key"_a);
|
||||
t.def(
|
||||
"__setitem__",
|
||||
[set, ext](T& self, Coords pnt, const V& val) {
|
||||
Coords s = (self.*ext)();
|
||||
int x = PyIndex(std::get<0>(pnt), std::get<0>(s), "x");
|
||||
int y = PyIndex(std::get<1>(pnt), std::get<1>(s), "y");
|
||||
set(self, x, y, val);
|
||||
},
|
||||
"key"_a, "value"_a);
|
||||
}
|
||||
|
||||
template <typename B> py::class_<B> BindBlock(py::module_& m, const char* name) {
|
||||
const char* frombytes_doc = R"doc(
|
||||
Create a new {0} by copying a bytes-like object.
|
||||
@ -259,11 +331,11 @@ template <typename B> py::class_<BlockTexture<B>> BindBlockTexture(py::module_&
|
||||
block_texture.def_static("from_bytes", &BufferToTexture<BTex>, "data"_a, "width"_a, "height"_a,
|
||||
Format(from_bytes_str, name).c_str());
|
||||
|
||||
block_texture.def_property_readonly("width_blocks", &BTex::BlocksX, "The width of the texture in blocks.");
|
||||
block_texture.def_property_readonly("height_blocks", &BTex::BlocksY, "The height of the texture in blocks.");
|
||||
block_texture.def_property_readonly("size_blocks", &BTex::BlocksXY, "The dimensions of the texture in blocks.");
|
||||
block_texture.def_property_readonly("width_blocks", &BTex::bwidth, "The width of the texture in blocks.");
|
||||
block_texture.def_property_readonly("height_blocks", &BTex::bheight, "The height of the texture in blocks.");
|
||||
block_texture.def_property_readonly("size_blocks", &BTex::bsize, "The dimensions of the texture in blocks.");
|
||||
|
||||
DefSubscript2D(block_texture, &BTex::GetBlock, &BTex::SetBlock, &BTex::BlocksXY);
|
||||
DefSubscript2D(block_texture, &BTex::get_block, &BTex::set_block, &BTex::bsize);
|
||||
|
||||
return std::move(block_texture);
|
||||
}
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
namespace quicktex::tests {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
template <typename T> constexpr auto make_arrays() {
|
||||
std::vector<std::array<T, xsimd::batch<T>::size>> arrays;
|
||||
std::array<T, xsimd::batch<T>::size> buffer;
|
||||
|
@ -21,14 +21,12 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "util/ranges.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/math.h"
|
||||
#include "util/ranges.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
uint16_t BC1Block::GetColor0Raw() const { return pack<uint16_t>(_color0, 8); }
|
||||
uint16_t BC1Block::GetColor1Raw() const { return pack<uint16_t>(_color1, 8); }
|
||||
|
||||
@ -40,10 +38,10 @@ BC1Block::SelectorArray BC1Block::GetSelectors() const {
|
||||
}
|
||||
|
||||
void BC1Block::SetSelectors(const BC1Block::SelectorArray& unpacked) {
|
||||
// for (unsigned y = 0; y < (unsigned)Height; y++) {
|
||||
// if (std::any_of(unpacked[y].begin(), unpacked[y].end(), [](uint8_t i) { return i > SelectorMax; }))
|
||||
// throw std::invalid_argument("Selector value out of bounds.");
|
||||
// }
|
||||
for (unsigned y = 0; y < (unsigned)Height; y++) {
|
||||
if (std::any_of(unpacked[y].begin(), unpacked[y].end(), [](uint8_t i) { return i > SelectorMax; }))
|
||||
throw std::invalid_argument("Selector value out of bounds.");
|
||||
}
|
||||
_selectors = map(unpacked, [](auto row) { return pack<uint8_t>(row, SelectorBits, true); });
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
class BC1Decoder final : public BlockDecoder<BlockTexture<BC1Block>> {
|
||||
|
@ -33,20 +33,18 @@
|
||||
#include "Histogram.h"
|
||||
#include "Matrix4x4.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "Vector4.h"
|
||||
#include "Vector4Int.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc1/OrderTable.h"
|
||||
#include "s3tc/bc1/SingleColorTable.h"
|
||||
#include "texture/Texture.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/bitwiseEnums.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
// constructors
|
||||
|
||||
BC1Encoder::BC1Encoder(unsigned int level, ColorMode color_mode, InterpolatorPtr interpolator)
|
||||
|
@ -29,10 +29,10 @@
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc1/SingleColorTable.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex {
|
||||
class Vector4;
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
struct BC1MatchEntry {
|
||||
uint8_t high;
|
||||
uint8_t low;
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Decoder.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
#include "s3tc/bc4/BC4Decoder.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Encoder.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
#include "s3tc/bc4/BC4Encoder.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
BC4Block::SelectorArray BC4Block::GetSelectors() const {
|
||||
auto packed = pack<uint64_t>(_selectors, 8);
|
||||
auto rows = unpack<uint16_t, Height>(packed, SelectorBits * Width);
|
||||
|
@ -22,10 +22,10 @@
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "BC4Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -22,10 +22,10 @@
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "BC4Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc4/BC4Decoder.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc4/BC4Encoder.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
#include "texture/BlockTexture.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
class BC5Encoder : public BlockEncoder<BlockTexture<BC5Block>> {
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
// region Interpolator implementation
|
||||
std::unique_ptr<Interpolator> Interpolator::MakeInterpolator(Interpolator::Type type) {
|
||||
switch (type) {
|
||||
|
70
quicktex/texture/BlockTexture.h
Normal file
70
quicktex/texture/BlockTexture.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "Texture.h"
|
||||
|
||||
namespace quicktex {
|
||||
template <typename B> class BlockTexture final : public Texture {
|
||||
private:
|
||||
std::vector<B> _blocks;
|
||||
unsigned _width_b;
|
||||
unsigned _height_b;
|
||||
|
||||
public:
|
||||
using BlockType = B;
|
||||
using Base = Texture;
|
||||
|
||||
/**
|
||||
* Create a new BlockTexture
|
||||
* @param width width of the texture in pixels. must be divisible by B::width
|
||||
* @param height height of the texture in pixels. must be divisible by B::height
|
||||
*/
|
||||
BlockTexture(int width, int height) : Base(width, height) {
|
||||
_width_b = (width + B::Width - 1) / B::Width;
|
||||
_height_b = (height + B::Height - 1) / B::Height;
|
||||
_blocks = std::vector<B>(_width_b * _height_b);
|
||||
}
|
||||
|
||||
constexpr unsigned bwidth() const { return _width_b; }
|
||||
constexpr unsigned bheight() const { return _height_b; }
|
||||
constexpr std::tuple<int, int> bsize() const { return std::tuple<int, int>(_width_b, _height_b); }
|
||||
|
||||
B get_block(unsigned x, unsigned y) const {
|
||||
if (x >= _width_b) throw std::out_of_range("x value out of range.");
|
||||
if (y >= _height_b) throw std::out_of_range("y value out of range.");
|
||||
return _blocks.at(x + (y * _width_b));
|
||||
}
|
||||
|
||||
void set_block(unsigned x, unsigned y, const B &val) {
|
||||
if (x >= _width_b) throw std::out_of_range("x value out of range.");
|
||||
if (y >= _height_b) throw std::out_of_range("y value out of range.");
|
||||
_blocks.at(x + (y * _width_b)) = val;
|
||||
}
|
||||
|
||||
size_t nbytes() const noexcept override { return _blocks.size() * sizeof(B); }
|
||||
|
||||
const uint8_t *data() const noexcept override { return reinterpret_cast<const uint8_t *>(_blocks.data()); }
|
||||
uint8_t *data() noexcept override { return reinterpret_cast<uint8_t *>(_blocks.data()); }
|
||||
};
|
||||
} // namespace quicktex
|
33
quicktex/texture/RawTexture.cpp
Normal file
33
quicktex/texture/RawTexture.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "RawTexture.h"
|
||||
|
||||
namespace quicktex {
|
||||
Color RawTexture::pixel(unsigned int x, unsigned int y) const {
|
||||
if (x < 0 || x >= width) throw std::invalid_argument("x value out of range.");
|
||||
if (y < 0 || y >= height) throw std::invalid_argument("y value out of range.");
|
||||
return _pixels.at(x + (y * width));
|
||||
}
|
||||
quicktex::Color& RawTexture::pixel(unsigned int x, unsigned int y) {
|
||||
if (x < 0 || x >= width) throw std::invalid_argument("x value out of range.");
|
||||
if (y < 0 || y >= height) throw std::invalid_argument("y value out of range.");
|
||||
return _pixels.at(x + (y * width));
|
||||
}
|
||||
} // namespace quicktex
|
97
quicktex/texture/RawTexture.h
Normal file
97
quicktex/texture/RawTexture.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "Color.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "OldColor.h"
|
||||
#include "texture/Texture.h"
|
||||
|
||||
namespace quicktex {
|
||||
class RawTexture : public Texture {
|
||||
using Base = Texture;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new RawTexture
|
||||
* @param width width of the texture in pixels
|
||||
* @param height height of the texture in pixels
|
||||
*/
|
||||
RawTexture(int width, int height) : Base(width, height), _pixels(width * height) {}
|
||||
|
||||
quicktex::Color pixel(unsigned x, unsigned y) const;
|
||||
|
||||
quicktex::Color &pixel(unsigned x, unsigned y);
|
||||
|
||||
quicktex::Color pixel_wrapped(unsigned x, unsigned y) const { return pixel(x % width, y % height); }
|
||||
|
||||
quicktex::Color &pixel_wrapped(unsigned x, unsigned y) { return pixel(x % width, y % height); }
|
||||
|
||||
size_t nbytes() const noexcept override { return static_cast<size_t>(width * height) * sizeof(quicktex::Color); }
|
||||
|
||||
template <int N, int M> quicktex::ColorBlock<N, M> get_block(int block_x, int block_y) const {
|
||||
if (block_x < 0) throw std::out_of_range("x value out of range.");
|
||||
if (block_y < 0) throw std::out_of_range("y value out of range.");
|
||||
|
||||
// coordinates in the image of the top-left pixel of the selected block
|
||||
quicktex::ColorBlock<N, M> block;
|
||||
int pixel_x = block_x * N;
|
||||
int pixel_y = block_y * M;
|
||||
|
||||
// slower pixel-wise copy if the block goes over the edges
|
||||
for (int x = 0; x < N; x++) {
|
||||
for (int y = 0; y < M; y++) { block.Set(x, y, pixel((pixel_x + x) % width, (pixel_y + y) % height)); }
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
template <int N, int M> void set_block(int block_x, int block_y, const quicktex::ColorBlock<N, M> &block) {
|
||||
if (block_x < 0) throw std::out_of_range("x value out of range.");
|
||||
if (block_y < 0) throw std::out_of_range("y value out of range.");
|
||||
|
||||
// coordinates in the image of the top-left pixel of the selected block
|
||||
int pixel_x = block_x * N;
|
||||
int pixel_y = block_y * M;
|
||||
|
||||
// slower pixel-wise copy if the block goes over the edges
|
||||
for (int x = 0; x < N; x++) {
|
||||
for (int y = 0; y < M; y++) { pixel((pixel_x + x) % width, (pixel_y + y) % height) = block.Get(x, y); }
|
||||
}
|
||||
}
|
||||
|
||||
virtual const uint8_t *data() const noexcept override { return reinterpret_cast<const uint8_t *>(_pixels.data()); }
|
||||
virtual uint8_t *data() noexcept override { return reinterpret_cast<uint8_t *>(_pixels.data()); }
|
||||
|
||||
protected:
|
||||
std::vector<quicktex::Color> _pixels;
|
||||
};
|
||||
} // namespace quicktex
|
64
quicktex/texture/Texture.h
Normal file
64
quicktex/texture/Texture.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
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
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "Color.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "OldColor.h"
|
||||
#include "Window.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
const unsigned width;
|
||||
const unsigned height;
|
||||
|
||||
virtual ~Texture() = default;
|
||||
|
||||
virtual std::tuple<unsigned, unsigned> Size() const { return {width, height}; }
|
||||
|
||||
/**
|
||||
* The texture's total size
|
||||
* @return The size of the texture in bytes.
|
||||
*/
|
||||
virtual size_t nbytes() const noexcept = 0;
|
||||
|
||||
virtual const uint8_t *data() const noexcept = 0;
|
||||
virtual uint8_t *data() noexcept = 0;
|
||||
|
||||
protected:
|
||||
Texture(unsigned width, unsigned height) : width(width), height(height) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace quicktex
|
90
quicktex/texture/Window.cpp
Normal file
90
quicktex/texture/Window.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
#include "texture/RawTexture.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
// Window
|
||||
Window::Window(RawTexture& texture, unsigned int width, unsigned int height, unsigned int x, unsigned int y)
|
||||
: width(width), height(height), x(x), y(y), _texture(texture) {
|
||||
assert(x < texture.width);
|
||||
assert(y < texture.height);
|
||||
}
|
||||
|
||||
Color& Window::pixel(unsigned px, unsigned py) {
|
||||
assert(px < width && py < height);
|
||||
return _texture.pixel(x + px, y + py);
|
||||
}
|
||||
|
||||
Color Window::pixel(unsigned px, unsigned py) const {
|
||||
assert(px < width && py < height);
|
||||
return _texture.pixel(x + px, y + py);
|
||||
}
|
||||
|
||||
WindowIterator Window::begin() { return WindowIterator(*this, 0, 0); }
|
||||
WindowIterator Window::end() { return WindowIterator(*this, 0, height); }
|
||||
WindowIterator Window::row_begin(unsigned int row) { return WindowIterator(*this, 0, row); }
|
||||
WindowIterator Window::row_end(unsigned int row) { return WindowIterator(*this, 0, row + 1); }
|
||||
|
||||
bool Window::operator==(const Window& rhs) const {
|
||||
return width == rhs.width && height == rhs.height && x == rhs.x && y == rhs.y && &_texture == &rhs._texture;
|
||||
}
|
||||
|
||||
// WindowIterator
|
||||
|
||||
WindowIterator::WindowIterator(Window& view, unsigned int x, unsigned int y) : x(x), y(y), _view(&view) {
|
||||
assert(x < view.width);
|
||||
assert(y < view.height || (y == view.height && x == 0));
|
||||
// if y == the height, and x == 0, then this is a sentinel for the end of iteration, and cannot be dereferenced
|
||||
}
|
||||
|
||||
WindowIterator& quicktex::WindowIterator::operator++() { // prefix increment
|
||||
x++;
|
||||
if (x >= _view->width) {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
WindowIterator WindowIterator::operator++(int) { // postfix increment
|
||||
WindowIterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
Color& WindowIterator::operator*() const { // dereference operator
|
||||
assert(_view != nullptr);
|
||||
assert(x < _view->width && y < _view->height);
|
||||
return _view->pixel(x, y);
|
||||
}
|
||||
|
||||
Color* WindowIterator::operator->() { return &(**this); } // returns a pointer to what's returned by operator*
|
||||
|
||||
bool WindowIterator::operator==(const WindowIterator& rhs) const {
|
||||
return x == rhs.x && y == rhs.y && _view == rhs._view;
|
||||
}
|
||||
|
||||
static_assert(std::forward_iterator<WindowIterator>);
|
||||
static_assert(sized_range<Window>);
|
||||
|
||||
} // namespace quicktex
|
82
quicktex/texture/Window.h
Normal file
82
quicktex/texture/Window.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Color.h"
|
||||
#include "util/ranges.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
// forward declarations
|
||||
class WindowIterator;
|
||||
class RawTexture;
|
||||
|
||||
/**
|
||||
* Class representing a window into a RawTexture
|
||||
*/
|
||||
class Window {
|
||||
public:
|
||||
typedef Color value_type;
|
||||
|
||||
const unsigned width, height;
|
||||
const unsigned x, y;
|
||||
|
||||
Window(RawTexture &texture, unsigned width, unsigned height, unsigned x, unsigned y);
|
||||
|
||||
Color &pixel(unsigned px, unsigned py);
|
||||
Color pixel(unsigned px, unsigned py) const;
|
||||
|
||||
WindowIterator begin();
|
||||
WindowIterator end();
|
||||
WindowIterator row_begin(unsigned row);
|
||||
WindowIterator row_end(unsigned row);
|
||||
|
||||
size_t size() const { return width * height; }
|
||||
|
||||
bool operator==(const Window &rhs) const;
|
||||
|
||||
private:
|
||||
RawTexture &_texture;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator returned by Window
|
||||
*/
|
||||
class WindowIterator {
|
||||
public:
|
||||
typedef long long difference_type;
|
||||
typedef Color value_type;
|
||||
|
||||
unsigned x, y;
|
||||
|
||||
WindowIterator(Window &view, unsigned x, unsigned y);
|
||||
WindowIterator() : x(0), y(0), _view(nullptr) {}
|
||||
|
||||
Color &operator*() const; // dereference
|
||||
Color *operator->(); // member access
|
||||
|
||||
WindowIterator &operator++(); // prefix increment
|
||||
WindowIterator operator++(int); // postfix increment
|
||||
bool operator==(const WindowIterator &rhs) const;
|
||||
|
||||
private:
|
||||
Window *_view;
|
||||
};
|
||||
|
||||
} // namespace quicktex
|
@ -35,7 +35,7 @@
|
||||
#define assert5bit(x) assert(x <= UINT5_MAX)
|
||||
#define assert6bit(x) assert(x <= UINT6_MAX)
|
||||
|
||||
namespace quicktex::util {
|
||||
namespace quicktex {
|
||||
|
||||
template <size_t N, typename S> S scale_from_8(S v) {
|
||||
static_assert(N < 8);
|
||||
@ -309,4 +309,4 @@ template <typename P, typename IR>
|
||||
inline constexpr P pack(IR r, size_t width, bool little_endian = true) {
|
||||
return pack<P>(r.begin(), r.end(), const_iterator(width), little_endian);
|
||||
}
|
||||
} // namespace quicktex::util
|
||||
} // namespace quicktex
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace quicktex::util {
|
||||
namespace quicktex {
|
||||
|
||||
// Thanks dkavolis
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#include "xsimd/xsimd.hpp"
|
||||
|
||||
namespace quicktex::util {
|
||||
namespace quicktex {
|
||||
|
||||
// std::ranges::range is currently not usable by default in libc++
|
||||
template <class T>
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
template <typename T> using requires_arch = xsimd::kernel::requires_arch<T>;
|
||||
|
||||
namespace quicktex::util::simd {
|
||||
namespace quicktex::simd {
|
||||
|
||||
namespace kernel {
|
||||
|
||||
@ -94,4 +94,4 @@ template <class A, class T> inline next_size_t<T> whadd(xsimd::batch<T, A> const
|
||||
return kernel::whadd(arg, A{});
|
||||
}
|
||||
|
||||
} // namespace quicktex::util::simd
|
||||
} // namespace quicktex::simd
|
@ -20,7 +20,7 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace quicktex::util {
|
||||
namespace quicktex {
|
||||
template <class> struct next_size;
|
||||
template <class T> using next_size_t = typename next_size<T>::type;
|
||||
template <class T> struct type_tag { using type = T; };
|
||||
|
Loading…
Reference in New Issue
Block a user