/*
* 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();
}