#include #include #include #include #include #include // STB image loading #define STB_IMAGE_IMPLEMENTATION #include "lib/stb_image.h" #include "lib/image_loader.hpp" std::unordered_map image_loader::image_cache = std::unordered_map(); paradiso::Bitmap image_loader::load(const std::string& filename) { if (image_cache.find(filename) == image_cache.end()) { std::string path = ASSET_PATH + filename; std::cout << "Loading " << path << std::endl; auto data = readBMP(path); image_cache[filename] = data; } return image_cache[filename]; } paradiso::Bitmap image_loader::readBMP(std::string& filename) { // Load with stb_image stbi_set_flip_vertically_on_load(true); // flip y axis for OpenGL int width, height, channels; unsigned char* image = stbi_load(filename.c_str(), &width, &height, &channels, 4); int size = width * height; if (!image) throw std::runtime_error("Error loading image"); // Convert to Vector of RGBA std::vector rgba = std::vector(size); for (int i = 0; i < size; i++) { // get rgba values int pos = i * 4; int r = image[pos + 0]; int g = image[pos + 1]; int b = image[pos + 2]; int a = image[pos + 3]; // bug in from_rgba. it expects bgra, not rgba auto val = paradiso::RGBA::from_rgba(b, g, r, a); rgba[i] = val; } // rotate image by 90 degrees CW std::vector rotated = std::vector(size); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int pos = y * width + x; int pos_rotated = x * height + (height - y - 1); rotated[pos_rotated] = rgba[pos]; } } // free image stbi_image_free(image); return paradiso::Bitmap::from_data( paradiso::Size{static_cast(height), static_cast(width)}, rotated); }