/* * Copyright (C) 2025 sillysagiri * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #include #include "header.hpp" #include "Timer.h" #include "fastlz.h" namespace fs = std::filesystem; int main(int argc, char **argv) { srand(time(0)); argparse::ArgumentParser program("sillyimage", "0.14"); Options opt; // Register argument { program.add_argument("-i", "--input") .help("input files") .default_value("") .required() .nargs(1) .store_into(opt.path_input); program.add_argument("-o", "--out") .help("output directory") .required() .store_into(opt.path_output); program.add_argument("-f", "--format") .help("texture format { rgb256, rgb16, indexed4, indexed16, indexed256, indexed32a8, indexed8a32 }") .default_value("rgb16") .choices("rgb256", "rgb16", "indexed4", "indexed16", "indexed256", "indexed32a8", "indexed8a32") .nargs(1) .store_into(opt.format); program.add_argument("-pf", "--palette-format") .help("palette format { rgb16, rgb256 }") .default_value("rgb16") .choices("rgb16", "rgb256") .nargs(1) .store_into(opt.palette_format); // program.add_argument("-c", "--compression") // .help("compression { none, fastlz }") // .default_value("fastlz") // .choices("none", "fastlz") // .nargs(1) // .store_into(opt.compression); program.add_argument("-be", "--big-endian") .help("enable big endian mode") .default_value(false) .nargs(1) .store_into(opt.enable_be); } // Parse argument { try { program.parse_args(argc, argv); // input list if (opt.path_input.empty() || !fs::exists(opt.path_input)) throw std::runtime_error(std::format("file doesnt exsist: \"{}\"", opt.path_input)); // output directory if (opt.path_output.empty() || !fs::is_directory(opt.path_output)) throw std::runtime_error(std::format("invalid output directory: \"{}\"", opt.path_output)); } catch(const std::exception &e) { std::cerr << std::format("Error: {}\n\n", e.what()) << program << "\n"; return 1; } } // Convert try { if (opt.format == "rgb256") { Image img; img.Load(opt.path_input); uint32_t img255_size = img.width*img.height; uint32_t img255[img255_size]; for (int i=0; i(img.data[i*4+3]) << 24) | // A (static_cast(img.data[i*4+0]) << 16) | // R (static_cast(img.data[i*4+1]) << 8) | // G static_cast(img.data[i*4+2]); // B if (opt.enable_be) img255[i] = to_be_int32(img255[i]); } Metadata meta; meta.format = Format::Format_RGB_256; meta.width = img.width; meta.height = img.height; meta.palette_count = 0; meta.original_size = img.data.size(); uint8_t compress[uint64_t(meta.original_size*1.5)]; meta.compress_size = fastlz_compress_level(1, img.data.data(), meta.original_size, compress); Palette palette(0); WriteOutput(opt, meta, palette, compress); } if (opt.format == "rgb16") { Image img; img.Load(opt.path_input); std::vector img16(img.width*img.height); // convert into RGB16 color for (int i=0; i(&meta.header), sizeof(uint64_t)); out.write(reinterpret_cast(&meta.version), sizeof(int8_t)); out.write(reinterpret_cast(&meta.format), sizeof(int8_t)); int8_t isBE = opt.enable_be; int8_t palette_format; if (opt.palette_format == "rgb16") palette_format = 1; if (opt.palette_format == "rgb256") palette_format = 2; out.write(reinterpret_cast(&isBE), sizeof(int8_t)); out.write(reinterpret_cast(&palette_format), sizeof(int8_t)); if (!opt.enable_be) { out.write(reinterpret_cast(&meta.width), sizeof(int16_t)); out.write(reinterpret_cast(&meta.height), sizeof(int16_t)); out.write(reinterpret_cast(&meta.palette_count), sizeof(int16_t)); out.write(reinterpret_cast(&meta.original_size), sizeof(int32_t)); out.write(reinterpret_cast(&meta.compress_size), sizeof(int32_t)); } else { uint16_t be_width = to_be_int16(meta.width); uint16_t be_height = to_be_int16(meta.height); uint16_t be_palette_count = to_be_int16(meta.palette_count); uint32_t be_original_size = to_be_int32(meta.original_size); uint32_t be_compress_size = to_be_int32(meta.compress_size); out.write(reinterpret_cast(&be_width), sizeof(uint16_t)); out.write(reinterpret_cast(&be_height), sizeof(uint16_t)); out.write(reinterpret_cast(&be_palette_count), sizeof(uint16_t)); out.write(reinterpret_cast(&be_original_size), sizeof(uint32_t)); out.write(reinterpret_cast(&be_compress_size), sizeof(uint32_t)); } if (!palette.empty()) { if (palette_format == 1) { uint16_t pal16[meta.palette_count]; for (int i=0; i(pal16), sizeof(uint16_t)*meta.palette_count); } else if (palette_format == 2) { uint32_t pal256[meta.palette_count]; for (int i=0; i(palette[i].a) << 24) | // A (static_cast(palette[i].r) << 16) | // R (static_cast(palette[i].g) << 8) | // G static_cast(palette[i].b); // B if (opt.enable_be) pal256[i] = to_be_int32(pal256[i]); } out.write(reinterpret_cast(pal256), sizeof(uint32_t)*meta.palette_count); } } out.write(reinterpret_cast(image_buffer), meta.compress_size); out.close(); }