121
src/bfl.cpp
Normal file
121
src/bfl.cpp
Normal 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
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
1724
src/stb_image_write.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user