This commit is contained in:
2024-07-19 17:12:42 -04:00
parent aac25ed35a
commit 79efe1c14d
6 changed files with 173 additions and 138 deletions

View File

@@ -0,0 +1,27 @@
#pragma once
#include <vector>
#include <string>
#include <ReTexture/flags.h>
namespace ReTexture {
class Texture {
private:
unsigned int width = 0;
unsigned int height = 0;
TextureFormat format;
TextureFlag flags;
void load(const std::string& file);
void loadBMP(const std::string& file);
void loadPNG(const std::string& file);
void invertY();
public:
std::vector<unsigned char> pixelData;
explicit Texture(const std::string& file);
Texture(const std::string& file, const TextureFlag& flags);
[[nodiscard]] unsigned int getWidth() const;
[[nodiscard]] unsigned int getHeight() const;
TextureFormat getTextureFormat();
TextureFlag getFlags();
};
}

View File

@@ -1,11 +1,17 @@
#pragma once
enum class RTextureFlag : unsigned int {
INVERT_Y = 0,
INVERT_X = 1,
};
namespace ReTexture {
enum TextureFlag {
INVERT_Y = 0,
INVERT_X = 1,
};
enum class RTextureFormat : bool {
RGB = false,
RGBA = true
};
inline TextureFlag operator|(TextureFlag a, TextureFlag b) {
return static_cast<TextureFlag>(static_cast<int>(a) | static_cast<int>(b));
}
enum class TextureFormat : bool {
RGB = false,
RGBA = true
};
}

View File

@@ -1,20 +0,0 @@
#pragma once
#include <vector>
#include <string>
#include <ReTexture/flags.h>
class RTexture {
private:
void load(const std::string& file);
void loadBMP(const std::string& file);
void loadPNG(const std::string& file);
void invertY();
public:
unsigned int width;
unsigned int height;
RTextureFormat format;
std::vector<unsigned char> pixelData;
RTexture(const std::string& file, const std::vector<RTextureFlag>& args);
explicit RTexture(const std::string& file);
};

View File

@@ -1,26 +1,27 @@
#include <ReTexture/rTexture.h>
#include <ReTexture/Texture.h>
#include <iostream>
using namespace ReTexture;
int main() {
auto* bmp = new RTexture("testImages/1.bmp", {RTextureFlag::INVERT_Y});
std::cout << "Bitmap Width: " << bmp->width << std::endl;
std::cout << "Bitmap Height: " << bmp->height << std::endl;
auto* bmp = new Texture("testImages/1.bmp", {TextureFlag::INVERT_Y});
std::cout << "Bitmap Width: " << bmp->getWidth() << std::endl;
std::cout << "Bitmap Height: " << bmp->getHeight() << std::endl;
if (bmp->format == RTextureFormat::RGB)
if (bmp->getTextureFormat() == TextureFormat::RGB)
std::cout << "Bitmap Format: RGB" << std::endl;
if (bmp->format == RTextureFormat::RGBA)
if (bmp->getTextureFormat() == TextureFormat::RGBA)
std::cout << "Bitmap Format: RGBA" << std::endl;
delete bmp;
auto* png = new RTexture("testImages/1.png", {RTextureFlag::INVERT_Y});
std::cout << "PNG width: " << png->width << std::endl;
std::cout << "PNG height: " << png->height << std::endl;
auto* png = new Texture("testImages/1.png", TextureFlag::INVERT_Y);
std::cout << "PNG width: " << png->getWidth() << std::endl;
std::cout << "PNG height: " << png->getHeight() << std::endl;
if (png->format == RTextureFormat::RGB)
if (png->getTextureFormat() == TextureFormat::RGB)
std::cout << "PNG Format: RGB" << std::endl;
if (png->format == RTextureFormat::RGBA)
if (png->getTextureFormat() == TextureFormat::RGBA)
std::cout << "PNG Format: RGBA" << std::endl;
delete png;
}

120
src/Texture.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include <fstream>
#include <algorithm>
#include <ReTexture/Texture.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
namespace ReTexture {
Texture::Texture(const std::string &file, const TextureFlag& flags) {
load(file);
if (flags & TextureFlag::INVERT_Y)
invertY();
this->flags = flags;
}
Texture::Texture(const std::string &file) {
*this = Texture(file, {});
}
void Texture::load(const std::string &file) {
std::ifstream ifStream(file, std::ios::in | std::ios::binary);
unsigned char bmpFileHeader[14];
ifStream.read(reinterpret_cast<char *>(bmpFileHeader), 14);
if (bmpFileHeader[0] == 'B' && bmpFileHeader[1] == 'M') {
ifStream.close();
loadBMP(file);
return;
}
//TODO determine if it's a PNG using the file header instead.
if (file.ends_with(".png"))
loadPNG(file);
}
void Texture::loadBMP(const std::string &file) {
std::ifstream bmpFile(file, std::ios::in | std::ios::binary);
if (!bmpFile.is_open())
return;
unsigned char bmpFileHeader[14];
unsigned char bmpInfoHeader[40];
bmpFile.read(reinterpret_cast<char *>(bmpFileHeader), 14);
bmpFile.read(reinterpret_cast<char *>(bmpInfoHeader), 40);
width = bmpInfoHeader[4] + (bmpInfoHeader[5] << 8) + (bmpInfoHeader[6] << 16) + (bmpInfoHeader[7] << 24);
height = bmpInfoHeader[8] + (bmpInfoHeader[9] << 8) + (bmpInfoHeader[10] << 16) + (bmpInfoHeader[11] << 24);
int rowPadded = (width * 3 + 3) & (~3);
pixelData.resize(width * height * 3);
std::vector<unsigned char> rowData(rowPadded);
for (int y = height - 1; y >= 0; --y) {
bmpFile.read(reinterpret_cast<char *>(rowData.data()), rowPadded);
for (int x = 0; x < width; ++x) {
pixelData[(y * width + x) * 3 + 2] = rowData[x * 3 + 0];
pixelData[(y * width + x) * 3 + 1] = rowData[x * 3 + 1];
pixelData[(y * width + x) * 3 + 0] = rowData[x * 3 + 2];
}
}
bmpFile.close();
format = TextureFormat::RGB;
}
void Texture::loadPNG(const std::string &file) {
int channels, w, h;
unsigned char* imageData = stbi_load(file.c_str(), &w, &h, &channels, 0);
if (imageData == nullptr)
return;
width = w;
height = h;
if (channels == 3)
format = TextureFormat::RGB;
if (channels == 4)
format = TextureFormat::RGBA;
pixelData.assign(imageData, imageData + width * height * channels);
stbi_image_free(imageData);
}
void Texture::invertY() {
unsigned int rowSize;
if (format == TextureFormat::RGB)
rowSize = width * 3;
if (format == TextureFormat::RGBA)
rowSize = width * 4;
std::vector<unsigned char> temp(rowSize);
for (unsigned int y = 0; y < height / 2; ++y) {
unsigned char *topRow = &pixelData[y * rowSize];
unsigned char *bottomRow = &pixelData[(height - y - 1) * rowSize];
std::copy(bottomRow, bottomRow + rowSize, temp.begin());
std::copy(topRow, topRow + rowSize, bottomRow);
std::copy(temp.begin(), temp.end(), topRow);
}
}
unsigned int Texture::getWidth() const {
return width;
}
unsigned int Texture::getHeight() const {
return height;
}
TextureFormat Texture::getTextureFormat() {
return format;
}
TextureFlag Texture::getFlags() {
return flags;
}
}

View File

@@ -1,99 +0,0 @@
#include <fstream>
#include <algorithm>
#include <ReTexture/rTexture.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
void RTexture::load(const std::string& file) {
std::ifstream ifStream(file, std::ios::in | std::ios::binary);
unsigned char bmpFileHeader[14];
ifStream.read(reinterpret_cast<char*>(bmpFileHeader), 14);
if (bmpFileHeader[0] == 'B' && bmpFileHeader[1] == 'M') {
ifStream.close();
loadBMP(file);
return;
}
//TODO
if (file.ends_with(".png"))
loadPNG(file);
}
void RTexture::loadBMP(const std::string& file) {
std::ifstream bmpFile(file, std::ios::in | std::ios::binary);
if (!bmpFile.is_open())
return;
unsigned char bmpFileHeader[14];
unsigned char bmpInfoHeader[40];
bmpFile.read(reinterpret_cast<char*>(bmpFileHeader), 14);
bmpFile.read(reinterpret_cast<char*>(bmpInfoHeader), 40);
width = bmpInfoHeader[4] + (bmpInfoHeader[5] << 8) + (bmpInfoHeader[6] << 16) + (bmpInfoHeader[7] << 24);
height = bmpInfoHeader[8] + (bmpInfoHeader[9] << 8) + (bmpInfoHeader[10] << 16) + (bmpInfoHeader[11] << 24);
int rowPadded = (width * 3 + 3) & (~3);
pixelData.resize(width * height * 3);
std::vector<unsigned char> rowData(rowPadded);
for (int y = height - 1; y >= 0; --y) {
bmpFile.read(reinterpret_cast<char*>(rowData.data()), rowPadded);
for (int x = 0; x < width; ++x) {
pixelData[(y * width + x) * 3 + 2] = rowData[x * 3 + 0];
pixelData[(y * width + x) * 3 + 1] = rowData[x * 3 + 1];
pixelData[(y * width + x) * 3 + 0] = rowData[x * 3 + 2];
}
}
bmpFile.close();
format = RTextureFormat::RGB;
}
void RTexture::loadPNG(const std::string &file) {
int channels, w, h;
unsigned char *imageData = stbi_load(file.c_str(), &w, &h, &channels, 0);
if (imageData == nullptr)
return;
width = w;
height = h;
if (channels == 3)
format = RTextureFormat::RGB;
if (channels == 4)
format = RTextureFormat::RGBA;
pixelData.assign(imageData, imageData + width * height * channels);
stbi_image_free(imageData);
}
RTexture::RTexture(const std::string &file, const std::vector<RTextureFlag> &args) {
load(file);
if (std::find(args.begin(), args.end(), RTextureFlag::INVERT_Y) != args.end())
invertY();
}
void RTexture::invertY() {
unsigned int rowSize;
if (format == RTextureFormat::RGB)
rowSize = width * 3;
if (format == RTextureFormat::RGBA)
rowSize = width * 4;
std::vector<unsigned char> temp(rowSize);
for (unsigned int y = 0; y < height / 2; ++y) {
unsigned char* topRow = &pixelData[y * rowSize];
unsigned char* bottomRow = &pixelData[(height - y - 1) * rowSize];
std::copy(bottomRow, bottomRow + rowSize, temp.begin());
std::copy(topRow, topRow + rowSize, bottomRow);
std::copy(temp.begin(), temp.end(), topRow);
}
}
RTexture::RTexture(const std::string& file) {
*this = RTexture(file, {});
}