mirror of
https://github.com/drewcassidy/quicktex.git
synced 2024-09-13 06:37:34 +00:00
Add texture creation from bytes
This commit is contained in:
parent
67751e87c7
commit
c70907ced2
@ -20,10 +20,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Block.h"
|
||||
#include "Color.h"
|
||||
@ -44,12 +47,14 @@ class Texture {
|
||||
*/
|
||||
virtual size_t Size() 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");
|
||||
}
|
||||
virtual uint8_t *DataMutable() = 0;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
@ -142,8 +147,10 @@ class RawTexture : public Texture {
|
||||
}
|
||||
};
|
||||
|
||||
virtual const uint8_t *Data() const noexcept override { return reinterpret_cast<const uint8_t *>(_pixels); }
|
||||
virtual uint8_t *Data() noexcept override { return reinterpret_cast<uint8_t *>(_pixels); }
|
||||
|
||||
protected:
|
||||
virtual uint8_t *DataMutable() override { return reinterpret_cast<uint8_t *>(_pixels); }
|
||||
|
||||
Color *_pixels;
|
||||
};
|
||||
@ -211,8 +218,10 @@ template <typename B> class BlockTexture : public Texture {
|
||||
|
||||
virtual size_t Size() const noexcept override { return (size_t)(BlocksX() * BlocksY()) * sizeof(B); }
|
||||
|
||||
virtual const uint8_t *Data() const noexcept override { return reinterpret_cast<const uint8_t *>(_blocks); }
|
||||
virtual uint8_t *Data() noexcept override { return reinterpret_cast<uint8_t *>(_blocks); }
|
||||
|
||||
protected:
|
||||
virtual uint8_t *DataMutable() override { return reinterpret_cast<uint8_t *>(_blocks); }
|
||||
|
||||
B *_blocks;
|
||||
};
|
||||
|
@ -83,48 +83,6 @@ 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<uint8_t *>(encoded_str.data()), reinterpret_cast<Color *>(decoded_str.data()), image_width, image_height);
|
||||
|
||||
auto bytes = py::bytes(encoded_str); // encoded data is copied here, unfortunately
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
py::bytes DecodeImage(const BlockDecoder &self, py::bytes encoded, unsigned image_width, unsigned image_height) {
|
||||
if (image_width % self.WidthInBlocks() != 0) throw std::invalid_argument("Width is not an even multiple of block_width");
|
||||
if (image_height % self.HeightInBlocks() != 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.HeightInBlocks() * self.WidthInBlocks())) * self.BlockSize();
|
||||
size_t color_size = size * sizeof(Color);
|
||||
|
||||
std::string encoded_str = (std::string)encoded; // encoded data is copied here, unfortunately
|
||||
std::string decoded_str = std::string(color_size, 0);
|
||||
|
||||
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);
|
||||
|
||||
auto bytes = py::bytes(decoded_str); // decoded data is copied here, unfortunately
|
||||
|
||||
return bytes;
|
||||
}*/
|
||||
|
||||
PYBIND11_MODULE(_quicktex, m) {
|
||||
m.doc() = "More Stuff";
|
||||
|
||||
@ -137,13 +95,18 @@ PYBIND11_MODULE(_quicktex, m) {
|
||||
texture.def_property_readonly("width", &Texture::Width);
|
||||
texture.def_property_readonly("height", &Texture::Height);
|
||||
|
||||
// texture.def_buffer([](Texture &t) { return py::buffer_info(t.Data(), t.Size()); });
|
||||
texture.def("to_bytes", [](const Texture &t) { return py::bytes(reinterpret_cast<const char *>(t.Data()), t.Size()); });
|
||||
|
||||
py::class_<RawTexture> raw_texture(m, "RawTexture", texture);
|
||||
|
||||
raw_texture.def(py::init<int, int>(), "width"_a, "height"_a);
|
||||
raw_texture.def("get_pixel", &RawTexture::GetPixel);
|
||||
raw_texture.def("set_pixel", &RawTexture::SetPixel);
|
||||
|
||||
InitS3TC(m);
|
||||
raw_texture.def_static("from_bytes", &BufferToTexture<RawTexture>, "data"_a, "width"_a, "height"_a);
|
||||
|
||||
// InitS3TC(m);
|
||||
}
|
||||
|
||||
} // namespace quicktex::bindings
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
@ -34,9 +36,30 @@ template <> struct type_caster<quicktex::Color>;
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
|
||||
using namespace pybind11::literals;
|
||||
|
||||
template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
|
||||
static_assert(std::is_base_of<Texture, T>::value);
|
||||
static_assert(std::is_constructible<T, int, int>::value);
|
||||
|
||||
auto info = buf.request(false);
|
||||
auto output = T(width, height);//std::make_shared<T>(width, height);
|
||||
auto dst_size = output.Size();
|
||||
|
||||
if (info.format != py::format_descriptor<uint8_t>::format()) throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
|
||||
if (info.size < (ssize_t)dst_size) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
|
||||
if (info.ndim == 1) {
|
||||
if (info.shape[0] < (ssize_t)dst_size) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
|
||||
if (info.strides[0] != 1) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
|
||||
} else {
|
||||
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");
|
||||
}
|
||||
|
||||
std::memcpy(output.Data(), info.ptr, dst_size);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename B> py::class_<BlockTexture<B>> BindBlockTexture(py::module_& m, const char* name) {
|
||||
using BTex = BlockTexture<B>;
|
||||
|
||||
@ -48,6 +71,8 @@ template <typename B> py::class_<BlockTexture<B>> BindBlockTexture(py::module_&
|
||||
block_texture.def("get_block", &BTex::GetBlock, "x"_a, "y"_a);
|
||||
block_texture.def("set_block", &BTex::SetBlock, "x"_a, "y"_a, "block"_a);
|
||||
|
||||
block_texture.def_static("from_bytes", &BufferToTexture<BTex>, "data"_a, "width"_a, "height"_a);
|
||||
|
||||
block_texture.def_property_readonly("blocks_x", &BTex::BlocksX);
|
||||
block_texture.def_property_readonly("blocks_y", &BTex::BlocksY);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user