Crafter.Asset/interfaces/Crafter.Asset-Texture.cppm

100 lines
No EOL
3.4 KiB
C++

/*
Crafter®.Asset
Copyright (C) 2026 Catcrafts®
catcrafts.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 3.0 as published by the Free Software Foundation;
This library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
module;
#define STB_IMAGE_IMPLEMENTATION
#include "../lib/stb_image.h"
export module Crafter.Asset:Texture;
import std;
import Crafter.Math;
namespace fs = std::filesystem;
export namespace Crafter {
enum class OpaqueType : std::uint8_t {
FullyOpaque, // All pixels have A of 255
SemiOpaque, // All pixels have A of 0 or 255 (no blending needed)
Transparent // Color blending is used
};
template <typename T>
struct TextureAsset {
std::uint16_t sizeX;
std::uint16_t sizeY;
OpaqueType opaque;
std::vector<T> pixels;
void Save(fs::path path) {
std::ofstream file(path, std::ios::binary);
file.write(reinterpret_cast<char*>(&sizeX), sizeof(sizeX));
file.write(reinterpret_cast<char*>(&sizeY), sizeof(sizeY));
file.write(reinterpret_cast<char*>(&opaque), sizeof(opaque));
file.write(reinterpret_cast<char*>(pixels.data()), pixels.size() * sizeof(T));
}
static TextureAsset<T> Load(fs::path path) {
TextureAsset<T> tex;
std::ifstream file(path, std::ios::binary);
file.read(reinterpret_cast<char*>(&tex.sizeX), sizeof(tex.sizeX));
file.read(reinterpret_cast<char*>(&tex.sizeY), sizeof(tex.sizeY));
file.read(reinterpret_cast<char*>(&tex.opaque), sizeof(tex.opaque));
tex.pixels.resize(tex.sizeX * tex.sizeY);
file.read(reinterpret_cast<char*>(tex.pixels.data()), tex.sizeX * tex.sizeY * sizeof(T));
return tex;
}
static TextureAsset<T> LoadPNG(fs::path path) requires (std::same_as<T, Vector<std::uint8_t, 4, 0>>) {
TextureAsset<T> tex;
std::filesystem::path abs = std::filesystem::absolute(path);
int sizeX;
int sizeY;
unsigned char* data = stbi_load(abs.string().c_str(), &sizeX, &sizeY, nullptr, 4);
tex.sizeX = sizeX;
tex.sizeY = sizeY;
tex.pixels.resize(tex.sizeX*tex.sizeY);
std::memcpy(tex.pixels.data(), data, tex.sizeX * tex.sizeY * 4);
tex.opaque = OpaqueType::FullyOpaque;
for(std::uint32_t i = 0; i < tex.sizeX* tex.sizeY; i++) {
if(tex.pixels[i].a != 255) {
tex.opaque = OpaqueType::SemiOpaque;
for(std::uint32_t i2 = i; i2 < tex.sizeX* tex.sizeY; i2++) {
if(tex.pixels[i].a != 0 && tex.pixels[i].a != 255) {
tex.opaque = OpaqueType::Transparent;
return tex;
}
}
return tex;
}
}
return tex;
}
};
}