Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-09-08 05:09:46 +03:00
parent 04127cb569
commit 1e3f84ec28
10 changed files with 3044 additions and 42 deletions

121
src/bfl.cpp Normal file
View File

@@ -0,0 +1,121 @@
/*
* bfl - BitFLip image format
* Copyright (C) 2025 Slendi <slendi@socopon.com>
* 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 <https://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <print>
#include <span>
#include <string_view>
#define BFL_IMPLEMENTATION
#include <bfl.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
static void print_bfl_header(bfl::Header const &h) {
auto const bool_prt = [](bool v) -> char const * { return v ? "yes" : "no"; };
std::println("BFL header:");
std::println(" width : {}", h.w);
std::println(" height : {}", h.h);
std::println(" flags (hex) : 0x{:02X}", h.flags);
std::println(" has_alpha : {}", bool_prt(h.flags & bfl::FLAG_HAS_ALPHA));
std::println(" img_raw : {}", bool_prt(h.flags & bfl::FLAG_IMG_RAW));
std::println(" tra_raw : {}", bool_prt(h.flags & bfl::FLAG_TRA_RAW));
std::println(" img_no_lz : {}", bool_prt(h.flags & bfl::FLAG_IMG_NOLZ));
std::println(" tra_no_lz : {}", bool_prt(h.flags & bfl::FLAG_TRA_NOLZ));
std::println(" image bytes : {}", h.img_len);
std::println(" alpha bytes : {}", h.tra_len);
}
inline std::vector<uint8_t> read_file(std::filesystem::path const &p) {
std::ifstream f(p, std::ios::binary);
return std::vector<uint8_t>((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>());
}
inline void write_file(std::filesystem::path const &p,
std::span<uint8_t const> d) {
std::ofstream f(p, std::ios::binary);
f.write(reinterpret_cast<char const *>(d.data()),
static_cast<std::streamsize>(d.size()));
}
int main(int argc, char const *argv[]) {
if (argc < 2) {
std::println(stderr,
"Usage:\n"
" {} <input> <output>\n"
" {} header <file.bfl>",
argv[0], argv[0]);
return 1;
}
if (argc == 3 && std::string_view(argv[1]) == "header") {
auto bytes{read_file(argv[2])};
auto v{bfl::parse_bfl(bytes)};
if (!v) {
std::println(stderr, "Invalid or truncated BFL: {}", argv[2]);
return 2;
}
print_bfl_header(v->hdr);
return 0;
}
if (argc != 3) {
std::println(stderr,
"Usage:\n"
" {} <input> <output>\n"
" {} header <file.bfl>",
argv[0], argv[0]);
return 1;
}
std::filesystem::path in{argv[1]}, outp{argv[2]};
bfl::Bitmap bmp;
if (in.extension() == ".bfl") {
bmp = bfl::Bitmap::decode(read_file(in));
} else {
int w, h, comp;
unsigned char *raw{stbi_load(in.string().c_str(), &w, &h, &comp, 4)};
if (!raw) {
std::println(stderr, "stbi_load failed on {}", in.string());
return 1;
}
std::span<uint32_t const> px{reinterpret_cast<uint32_t const *>(raw),
(size_t)w * (size_t)h};
bmp = bfl::Bitmap::from_rgba(px, w, h);
stbi_image_free(raw);
}
if (outp.extension() == ".bfl") {
auto bin{bmp.encode()};
write_file(outp, std::span<uint8_t const>(bin.data(), bin.size()));
} else {
auto rgba{bmp.to_rgba()};
stbi_write_png(outp.string().c_str(), bmp.width, bmp.height, 4, rgba.data(),
bmp.width * 4);
}
return 0;
}

7988
src/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

1724
src/stb_image_write.h Normal file

File diff suppressed because it is too large Load Diff