#include #include #include #include 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(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(bmpFileHeader), 14); bmpFile.read(reinterpret_cast(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 rowData(rowPadded); for (int y = height - 1; y >= 0; --y) { bmpFile.read(reinterpret_cast(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) { FILE *fp = fopen(file.c_str(), "rb"); if (!fp) { fprintf(stderr, "Could not open file %s for reading\n", file.c_str()); return; } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png) { fprintf(stderr, "Could not create png read struct\n"); fclose(fp); return; } png_infop info = png_create_info_struct(png); if (!info) { fprintf(stderr, "Could not create png info struct\n"); png_destroy_read_struct(&png, nullptr, nullptr); fclose(fp); return; } if (setjmp(png_jmpbuf(png))) { fprintf(stderr, "Error during png creation\n"); png_destroy_read_struct(&png, &info, nullptr); fclose(fp); return; } png_init_io(png, fp); png_read_info(png, info); width = png_get_image_width(png, info); height = png_get_image_height(png, info); png_byte color_type = png_get_color_type(png, info); png_byte bit_depth = png_get_bit_depth(png, info); if (bit_depth == 16) png_set_strip_16(png); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) png_set_filler(png, 0xFF, PNG_FILLER_AFTER); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); png_read_update_info(png, info); pixelData.resize(png_get_rowbytes(png, info) * height); std::vector row_pointers(height); for (unsigned y = 0; y < height; ++y) { row_pointers[y] = pixelData.data() + y * png_get_rowbytes(png, info); } png_read_image(png, row_pointers.data()); fclose(fp); png_destroy_read_struct(&png, &info, nullptr); if (color_type & PNG_COLOR_MASK_ALPHA) format = RTextureFormat::RGBA; if (!(color_type & PNG_COLOR_MASK_ALPHA)) format = RTextureFormat::RGB; } RTexture::RTexture(const std::string &file, const std::vector &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 temp(rowSize); for (uint 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); } }