165 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <asset_parser/assets/texture.hpp>
 | |
| #include <lz4.h>
 | |
| 
 | |
| namespace Assets {
 | |
| 
 | |
| /* static */ void TextureAsset::pack(const PackageData &data, const std::filesystem::path &out_path)
 | |
| {
 | |
| 	const auto &[metadata, texture_metadata, pixels] = data;
 | |
| 
 | |
| 	auto stream = std::ofstream { out_path, std::ios::binary | std::ios::trunc };
 | |
| 	if (!stream.is_open())
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to open ofstream for packing texture at: {}", out_path.string())
 | |
| 		};
 | |
| 	}
 | |
| 	stream.seekp(0);
 | |
| 
 | |
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 	stream.write((char *)¤t_version, sizeof(current_version));
 | |
| 
 | |
| 	stream.write((char *)&metadata, sizeof(metadata));
 | |
| 	stream.write((char *)&texture_metadata, sizeof(texture_metadata));
 | |
| 
 | |
| 	constexpr auto number_of_blobs = uint32_t { 1 };
 | |
| 	stream.write((char *)&number_of_blobs, sizeof(number_of_blobs));
 | |
| 
 | |
| 	auto pixels_metadata = BlobMetadata {
 | |
| 		.tag = BlobMetadata::Tag::color,
 | |
| 		.offset = static_cast<size_t>(stream.tellp()) + sizeof(BlobMetadata),
 | |
| 		.compression_type = CompressionType::None,
 | |
| 		.compressed_size = pixels.size(),
 | |
| 		.uncompressed_size = pixels.size(),
 | |
| 	};
 | |
| 
 | |
| 	stream.write((char *)&pixels_metadata, sizeof(pixels_metadata));
 | |
| 	stream.write((char *)&pixels[0], static_cast<long>(pixels.size()));
 | |
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| }
 | |
| 
 | |
| TextureAsset::TextureAsset(const std::filesystem::path &path)
 | |
| {
 | |
| 	m_stream = std::ifstream { path, std::ios::binary };
 | |
| 	if (!m_stream.is_open())
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to open ifstream for loading texture asset at: {}", path.string())
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 	m_stream.read((char *)&version, sizeof(version));
 | |
| 	m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata));
 | |
| 	m_stream.read((char *)&m_metadata, sizeof(m_metadata));
 | |
| 
 | |
| 	auto num_blobs = uint32_t {};
 | |
| 	m_stream.read((char *)&num_blobs, sizeof(num_blobs));
 | |
| 	if (num_blobs != 1)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Failed to load texture asset: invalid number of blobs: {}", num_blobs)
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	m_stream.read((char *)&m_pixel_blob_metadata, sizeof(m_pixel_blob_metadata));
 | |
| 	if (m_pixel_blob_metadata.tag != BlobMetadata::Tag::color)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format(
 | |
| 			    "Failed to load texture asset: invalid blob tag, expected {}, got {}",
 | |
| 			    std::to_underlying(BlobMetadata::Tag::color),
 | |
| 			    std::to_underlying(m_pixel_blob_metadata.tag)
 | |
| 			),
 | |
| 		};
 | |
| 	}
 | |
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| }
 | |
| 
 | |
| void TextureAsset::unpack_blob(
 | |
|     BlobMetadata::Tag tag,
 | |
|     std::byte *destination,
 | |
|     size_t destination_capacity
 | |
| )
 | |
| {
 | |
| 	if (tag != BlobMetadata::Tag::color)
 | |
| 	{
 | |
| 		throw std::runtime_error {
 | |
| 			std::format("Invalid tag for unpack_blob of TextureAsset: {}", std::to_underlying(tag))
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	m_stream.seekg(static_cast<long>(m_pixel_blob_metadata.offset));
 | |
| 	switch (m_pixel_blob_metadata.compression_type)
 | |
| 	{
 | |
| 	case Assets::CompressionType::None:
 | |
| 		if (m_pixel_blob_metadata.uncompressed_size != m_pixel_blob_metadata.compressed_size)
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextureAsset: "
 | |
| 			    "compressed/uncompressed size mismatch for no compression "
 | |
| 			    "type"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		if (m_pixel_blob_metadata.uncompressed_size > destination_capacity)
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextureAsset: "
 | |
| 			    "uncompressed_size > destination_capacity, unpacking "
 | |
| 			    "would result in segfault"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		if (!m_stream.is_open())
 | |
| 		{
 | |
| 			throw std::runtime_error(
 | |
| 			    "Failed to unpack blob from TextureAsset: ifstream is "
 | |
| 			    "closed"
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		m_stream.read(
 | |
| 		    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
 | |
| 		    (char *)destination,
 | |
| 		    static_cast<long>(m_pixel_blob_metadata.uncompressed_size)
 | |
| 		);
 | |
| 
 | |
| 		return;
 | |
| 
 | |
| 	default:
 | |
| 		throw std::runtime_error(
 | |
| 		    std::format(
 | |
| 		        "Failed to unpack blob from TextureAsset: unsupported "
 | |
| 		        "compression type: {}",
 | |
| 		        std::to_underlying(m_pixel_blob_metadata.compression_type)
 | |
| 		    )
 | |
| 		);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextureAsset::get_asset_metadata() const -> const Asset::Metadata &
 | |
| {
 | |
| 	return m_asset_metadata;
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextureAsset::get_metadata() const -> const Metadata &
 | |
| {
 | |
| 	return m_metadata;
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto TextureAsset::get_blob_metadata(BlobMetadata::Tag tag) const
 | |
|     -> const BlobMetadata &
 | |
| {
 | |
| 	if (tag != BlobMetadata::Tag::color)
 | |
| 	{
 | |
| 		throw std::runtime_error { std::format(
 | |
| 			"Invalid tag for get_blob_metadata of TextureAsset: {}",
 | |
| 			std::to_underlying(tag)
 | |
| 		) };
 | |
| 	}
 | |
| 
 | |
| 	return m_pixel_blob_metadata;
 | |
| }
 | |
| 
 | |
| } // namespace Assets
 |