Various improvements
This commit is contained in:
parent
1b93f5d09d
commit
37b80d3624
7 changed files with 474 additions and 83 deletions
57
.vscode/settings.json
vendored
57
.vscode/settings.json
vendored
|
@ -29,6 +29,61 @@
|
|||
"deque": "cpp",
|
||||
"__memory": "cpp",
|
||||
"locale": "cpp",
|
||||
"vector": "cpp"
|
||||
"vector": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"exception": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"string_view": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"variant": "cpp",
|
||||
"__config": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__errc": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__locale": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"__tree": "cpp",
|
||||
"__verbose_abort": "cpp"
|
||||
}
|
||||
}
|
107
bitmapx16.cpp
107
bitmapx16.cpp
|
@ -17,6 +17,7 @@ float BitmapX16::closeness_to_color(PaletteEntry a, PaletteEntry b) {
|
|||
void BitmapX16::set_bpp(uint8_t bpp) {
|
||||
this->bpp = bpp;
|
||||
quantize_colors = true;
|
||||
operations_pending = true;
|
||||
}
|
||||
uint8_t BitmapX16::get_bpp() const {
|
||||
return bpp;
|
||||
|
@ -27,6 +28,7 @@ void BitmapX16::set_significant(uint8_t value) {
|
|||
}
|
||||
significant_count = value;
|
||||
quantize_colors = true;
|
||||
operations_pending = true;
|
||||
}
|
||||
uint8_t BitmapX16::get_significant() const {
|
||||
return significant_count;
|
||||
|
@ -39,6 +41,7 @@ size_t BitmapX16::get_height() const {
|
|||
}
|
||||
void BitmapX16::enable_dithering(bool enabled) {
|
||||
dither = enabled;
|
||||
operations_pending = true;
|
||||
}
|
||||
bool BitmapX16::dithering_enabled() const {
|
||||
return dither;
|
||||
|
@ -50,6 +53,26 @@ void BitmapX16::resize(size_t w, size_t h) {
|
|||
void BitmapX16::queue_resize(size_t w, size_t h) {
|
||||
tw = w;
|
||||
th = h;
|
||||
operations_pending = true;
|
||||
}
|
||||
void BitmapX16::apply_operations(BitmapX16Operation operations) {
|
||||
if (operations & BitmapX16Operation::Resize) {
|
||||
if (tw != 0 && th != 0) {
|
||||
resize(tw, th);
|
||||
tw = 0;
|
||||
th = 0;
|
||||
}
|
||||
}
|
||||
if (operations & BitmapX16Operation::Quantize) {
|
||||
if (significant_count != 0) {
|
||||
image->quantizeColors(significant_count);
|
||||
image->quantizeDither(dither);
|
||||
image->quantize();
|
||||
}
|
||||
}
|
||||
if (operations & BitmapX16Operation::PreparePalette) {
|
||||
|
||||
}
|
||||
}
|
||||
void BitmapX16::apply() {
|
||||
if (tw != 0 && th != 0) {
|
||||
|
@ -70,6 +93,7 @@ void BitmapX16::apply() {
|
|||
}
|
||||
image->quantize();
|
||||
generate_palette();
|
||||
operations_pending = false;
|
||||
}
|
||||
uint8_t BitmapX16::extra_to_real_palette(uint8_t idx) {
|
||||
return image_palette_count + idx;
|
||||
|
@ -83,7 +107,11 @@ void BitmapX16::write_x16(const char *filename) {
|
|||
size_t outpixelsize;
|
||||
size_t pixelCount;
|
||||
pixels_per_byte = (8/bpp);
|
||||
apply();
|
||||
if (operations_pending) {
|
||||
apply();
|
||||
} else {
|
||||
generate_palette();
|
||||
}
|
||||
w = image->columns();
|
||||
h = image->rows();
|
||||
printf("Image size: (%lu, %lu)\n", w, h);
|
||||
|
@ -306,48 +334,47 @@ uint8_t BitmapX16::get_orable_pixel(uint8_t pixelinbyte, uint8_t color) {
|
|||
BitmapX16::BitmapX16() {
|
||||
palette_entries = vector<PaletteEntry>();
|
||||
}
|
||||
void BitmapX16::generate_palette() {
|
||||
size_t min;
|
||||
uint16_t max;
|
||||
if (!generate_palette_enabled || !write_palette) {
|
||||
significant_count = write_palette ? palette_entries.size() : 0;
|
||||
max = significant_count;
|
||||
min = 256 - max;
|
||||
if (min >= 16 && write_palette) {
|
||||
significant_start = 16;
|
||||
}
|
||||
if (max > 256) max = 256;
|
||||
if (bpp == 0) {
|
||||
if (max <= 4) {
|
||||
bpp = 2;
|
||||
} else if (max <= 16) {
|
||||
bpp = 4;
|
||||
} else {
|
||||
bpp = 8;
|
||||
}
|
||||
}
|
||||
return;
|
||||
void BitmapX16::prepare_palette() {
|
||||
size_t max_start;
|
||||
uint16_t max_colors;
|
||||
if (!generate_palette_enabled) {
|
||||
max_colors = palette_entries.size();
|
||||
} else {
|
||||
max_colors = image->colorMapSize();
|
||||
}
|
||||
max = (uint16_t)image->colorMapSize();
|
||||
if (max > 256) max = 256;
|
||||
max_start = 256 - max_colors;
|
||||
if (max_start >= target_palette_start) {
|
||||
significant_start = target_palette_start;
|
||||
} else {
|
||||
significant_start = max_start;
|
||||
}
|
||||
if (max_colors > 256) max_colors = 256;
|
||||
if (bpp == 0) {
|
||||
if (max <= 4) {
|
||||
if (max_colors <= 4) {
|
||||
bpp = 2;
|
||||
} else if (max <= 16) {
|
||||
} else if (max_colors <= 16) {
|
||||
bpp = 4;
|
||||
} else {
|
||||
bpp = 8;
|
||||
}
|
||||
}
|
||||
min = 256 - (1 << bpp);
|
||||
if (min >= 16) {
|
||||
significant_start = 16;
|
||||
if (generate_palette_enabled) {
|
||||
if (significant_count == 0) {
|
||||
significant_count = max_colors;
|
||||
}
|
||||
}
|
||||
if (significant_count == 0) {
|
||||
significant_count = max;
|
||||
image_palette_count = max_colors;
|
||||
if (debug & DebugShowSignificant) {
|
||||
uint16_t significant_end = significant_start + significant_count;
|
||||
uint16_t image_end = significant_start + image_palette_count;
|
||||
printf("Significant: %u-%u, %u entries\n", significant_start, significant_end, significant_count);
|
||||
printf("Image: %u-%u, %u entries\n", significant_start, image_end, image_palette_count);
|
||||
}
|
||||
bitmask = (1 << bpp) - 1;
|
||||
image_palette_count = max;
|
||||
}
|
||||
void BitmapX16::generate_palette() {
|
||||
uint16_t max_colors;
|
||||
prepare_palette();
|
||||
max_colors = image_palette_count;
|
||||
palette_entries.clear();
|
||||
for (uint16_t i = 0; i < image_palette_count; i++) {
|
||||
ColorRGB map_color = image->colorMap(i);
|
||||
|
@ -368,6 +395,7 @@ void BitmapX16::generate_palette() {
|
|||
}
|
||||
uint8_t BitmapX16::add_palette_entry(PaletteEntry entry) {
|
||||
extra_palette_entries.push_back(entry);
|
||||
operations_pending = true;
|
||||
return (uint8_t)(extra_palette_entries.size() - 1);
|
||||
}
|
||||
uint8_t BitmapX16::color_to_palette_entry(const ColorRGB &rgb) {
|
||||
|
@ -377,7 +405,7 @@ uint8_t BitmapX16::color_to_palette_entry(const ColorRGB &rgb) {
|
|||
if (debug & DebugShowCloseness) {
|
||||
printf("Closest color for %s: ", color.to_string().c_str());
|
||||
}
|
||||
for (size_t i = 0; i < image_palette_count; i++) {
|
||||
for (size_t i = 0; i < image_palette_count && i < (1 << bpp); i++) {
|
||||
float possibility_closeness = closeness_to_color(palette_entries[i], color);
|
||||
//printf("Closeness: %f", possibility_closeness);
|
||||
if (possibility_closeness < closeness) {
|
||||
|
@ -433,19 +461,14 @@ void BitmapX16::set_palette(vector<PaletteEntry> entries) {
|
|||
palette_entries.shrink_to_fit();
|
||||
extra_palette_entries.clear();
|
||||
generate_palette_enabled = false;
|
||||
image->quantizeColors(entries.size());
|
||||
image->quantizeColorSpace(MagickCore::RGBColorspace);
|
||||
image->colorMapSize(entries.size());
|
||||
for (uint16_t i = 0; i < entries.size(); i++) {
|
||||
image->colorMap(i, entries[i].toColor());
|
||||
}
|
||||
image->quantize();
|
||||
operations_pending = true;
|
||||
}
|
||||
void BitmapX16::enable_palette_generation() {
|
||||
generate_palette_enabled = true;
|
||||
operations_pending = true;
|
||||
}
|
||||
bool BitmapX16::palette_generation_enabled() const {
|
||||
return generate_palette_enabled && write_palette;
|
||||
return generate_palette_enabled;
|
||||
}
|
||||
void BitmapX16::read_palette(const char *filename) {
|
||||
size_t fsize = std::filesystem::file_size(filename);
|
||||
|
|
30
bitmapx16.h
30
bitmapx16.h
|
@ -2,12 +2,22 @@
|
|||
#include <vector>
|
||||
#include <Magick++.h>
|
||||
#include "palette.h"
|
||||
#include <stdint.h>
|
||||
using namespace Magick;
|
||||
using std::vector;
|
||||
enum BitmapX16DebugFlags : int {
|
||||
enum BitmapX16DebugFlags : uint16_t {
|
||||
DebugNone = 0,
|
||||
DebugShowPalette = (1 << 0),
|
||||
DebugShowCloseness = (1 << 1)
|
||||
DebugShowCloseness = (1 << 1),
|
||||
DebugShowSignificant = (1 << 2),
|
||||
|
||||
};
|
||||
enum BitmapX16Operation : uint16_t {
|
||||
None = 0,
|
||||
Resize = (1 << 0),
|
||||
Quantize = (1 << 1),
|
||||
PreparePalette = (1 << 2),
|
||||
GeneratePalette = (1 << 15),
|
||||
};
|
||||
class BitmapX16 {
|
||||
/// \brief Bits per pixel of the image
|
||||
|
@ -26,10 +36,12 @@ class BitmapX16 {
|
|||
bool quantize_colors = false;
|
||||
/// \brief Enables LZSA compression
|
||||
bool compress = false;
|
||||
/// \brief False to set the used palette to 0, and palette start also to 0.
|
||||
bool write_palette = true;
|
||||
/// \brief Whether or not an operation is pending.
|
||||
bool operations_pending = false;
|
||||
/// \brief True if the palette should be generated, false if it has been set manually and shouldn't be regenerated.
|
||||
bool generate_palette_enabled = true;
|
||||
/// \brief The intended start of the palette.
|
||||
uint8_t target_palette_start = 16;
|
||||
/// \brief Current width
|
||||
size_t w = 0;
|
||||
/// \brief Current height
|
||||
|
@ -52,10 +64,6 @@ class BitmapX16 {
|
|||
uint8_t image_palette_count = 0;
|
||||
/// \brief Generates a palette from the current image
|
||||
void generate_palette();
|
||||
/// \brief Actually resizes the image. User code should call queue_resize then apply
|
||||
/// \param w The width to resize to
|
||||
/// \param h The height to resize to
|
||||
void resize(size_t w, size_t h);
|
||||
/// \brief Gets the pixel index within this image based on X and Y values, as well as the width of the image
|
||||
/// \param x The X value of the pixel
|
||||
/// \param y The Y value of the pixel
|
||||
|
@ -83,6 +91,7 @@ class BitmapX16 {
|
|||
uint8_t color_to_palette_entry(const ColorRGB &rgb);
|
||||
uint8_t extra_to_real_palette(uint8_t idx);
|
||||
float closeness_to_color(PaletteEntry a, PaletteEntry b);
|
||||
void prepare_palette();
|
||||
public:
|
||||
vector<PaletteEntry> get_palette() const;
|
||||
vector<PaletteEntry> get_extra_entries() const;
|
||||
|
@ -90,6 +99,11 @@ class BitmapX16 {
|
|||
/// \brief Sets the palette to use
|
||||
/// \param entries The entries to replace the existing palette
|
||||
void set_palette(vector<PaletteEntry> entries);
|
||||
/// \brief Actually resizes the image. User code should call queue_resize then apply
|
||||
/// \param w The width to resize to
|
||||
/// \param h The height to resize to
|
||||
void resize(size_t w, size_t h);
|
||||
void apply_operations(BitmapX16Operation operations);
|
||||
/// \brief Enables palette generation after disabling it with set_palette.
|
||||
void enable_palette_generation();
|
||||
/// \brief Checks the status of palette generation
|
||||
|
|
26
main.cpp
26
main.cpp
|
@ -266,6 +266,12 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
if (tbpp == 0) tbpp = 8;
|
||||
if (tcolorcount == 0) tcolorcount = (1 << tbpp);
|
||||
if (probe_only) {
|
||||
tw = 0;
|
||||
th = 0;
|
||||
tbpp = 0;
|
||||
tcolorcount = 0;
|
||||
}
|
||||
try {
|
||||
BitmapX16 bitmap;
|
||||
bitmap.enable_compression(compress);
|
||||
|
@ -276,6 +282,11 @@ int main(int argc, char **argv) {
|
|||
} else {
|
||||
printf("Loading PC image file '%s' to be converted to the X16 bitmap format...\n", input);
|
||||
printf("Using at most %u colors (excluding border color) at %u bpp\n", tcolorcount, tbpp);
|
||||
if (palette_file != NULL) {
|
||||
printf("Using palette file '%s'\n", palette_file);
|
||||
} else {
|
||||
printf("Using generated palette.\n");
|
||||
}
|
||||
if (bitmap.compression_enabled()) printf("Compression enabled\n");
|
||||
bitmap.load_pc(input);
|
||||
}
|
||||
|
@ -292,6 +303,21 @@ int main(int argc, char **argv) {
|
|||
h = bitmap.get_height();
|
||||
uint8_t entry_count = bitmap.get_significant();
|
||||
uint8_t entry_start = bitmap.get_significant_start();
|
||||
printf("Image BPP: %u\n", tbpp);
|
||||
printf("Image size: (%u, %u)\n", w, h);
|
||||
printf("Palette starts at %u, has %u entries, and ends at %u\n", entry_start, entry_count == 0 ? 256 : entry_count, entry_start + entry_count);
|
||||
printf("Palette:\n");
|
||||
vector<PaletteEntry> entries = bitmap.get_palette();
|
||||
for (size_t i = 0; i < entries.size(); i+=8) {
|
||||
for (size_t j = 0; j < 8; j++) {
|
||||
if (i + j > entries.size()) {
|
||||
break;
|
||||
}
|
||||
printf("[%u] = %s, ", i + j, entries[i + j].to_string().c_str());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (reverse) {
|
||||
error_msg_part = "write the file";
|
||||
|
|
133
output.cpp
Normal file
133
output.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "output.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
ConsoleOutput::FormatType ConsoleOutput::format_type = ConsoleOutput::Text;
|
||||
std::string ConsoleOutput::CategoryPrefix(Category category) {
|
||||
if (format_type == Text) {
|
||||
switch (category) {
|
||||
case Debug:
|
||||
return "Debug: ";
|
||||
case Warning:
|
||||
return "WARNING: ";
|
||||
case Error:
|
||||
return "ERROR: ";
|
||||
case Info:
|
||||
case None:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
std::string output;
|
||||
switch (category) {
|
||||
case Debug:
|
||||
output = "DEBUG";
|
||||
break;
|
||||
case Info:
|
||||
output = "INFO";
|
||||
break;
|
||||
case Warning:
|
||||
output = "WARNING";
|
||||
break;
|
||||
case Error:
|
||||
output = "ERROR";
|
||||
break;
|
||||
default:
|
||||
if (format_type == Json) {
|
||||
output = "NONE";
|
||||
} else {
|
||||
output = "";
|
||||
}
|
||||
}
|
||||
if (format_type == LogStyle) {
|
||||
output = "[" + output + "] ";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
std::string ConsoleOutput::InsertCategoryPrefix(Category category, std::string input) {
|
||||
std::string output = "";
|
||||
std::string categoryPrefix = CategoryPrefix(category);
|
||||
if (format_type == Json) {
|
||||
output = "{\"category\": \"";
|
||||
output += categoryPrefix;
|
||||
output += "\", \"text\": \"";
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
char inChar = input[i];
|
||||
switch (inChar) {
|
||||
case '\"':
|
||||
output += "\\\"";
|
||||
break;
|
||||
case '\n':
|
||||
output += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
output += "\\r";
|
||||
break;
|
||||
case '\\':
|
||||
output += '\\\\';
|
||||
break;
|
||||
case '/':
|
||||
output += "\\/";
|
||||
break;
|
||||
case '\b':
|
||||
output += "\\b";
|
||||
break;
|
||||
case '\t':
|
||||
output += '\\t';
|
||||
break;
|
||||
default:
|
||||
output += inChar;
|
||||
}
|
||||
}
|
||||
output += "\"}";
|
||||
} else {
|
||||
for (size_t i = 0; i < input.length(); i++) {
|
||||
char inChar = input[i];
|
||||
if (inChar == '\n' || (inChar == '\r' && (i + 1 < input.length() && input[i] != '\n'))) {
|
||||
output += "\n";
|
||||
output += categoryPrefix;
|
||||
} else {
|
||||
output += inChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
void ConsoleOutput::Write(Category category, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
std::string output = VFormat(fmt, args);
|
||||
va_end(args);
|
||||
output = InsertCategoryPrefix(category, output);
|
||||
printf("%s", output.c_str());
|
||||
}
|
||||
void ConsoleOutput::WriteLn(Category category, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
std::string output = VFormat(fmt, args);
|
||||
va_end(args);
|
||||
output = InsertCategoryPrefix(category, output);
|
||||
printf("%s", output.c_str());
|
||||
}
|
||||
std::string ConsoleOutput::Format(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
std::string output = VFormat(fmt, args);
|
||||
va_end(args);
|
||||
return output;
|
||||
}
|
||||
std::string ConsoleOutput::VFormat(const char *fmt, va_list args) {
|
||||
size_t len = 0;
|
||||
char *buf = NULL;
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
len = vsnprintf(NULL, 0, fmt, args_copy);
|
||||
va_end(args_copy);
|
||||
buf = (char*)malloc(len);
|
||||
va_copy(args_copy, args);
|
||||
len = vsnprintf(buf, len, fmt, args_copy);
|
||||
va_end(args_copy);
|
||||
std::string output(buf);
|
||||
free(buf);
|
||||
return output;
|
||||
}
|
31
output.h
Normal file
31
output.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
class ConsoleOutput;
|
||||
class ConsoleOutput {
|
||||
public:
|
||||
enum FormatType {
|
||||
Text,
|
||||
LogStyle,
|
||||
Json
|
||||
}
|
||||
enum Category {
|
||||
None,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
};
|
||||
static FormatType format_type;
|
||||
static std::string CategoryPrefix(Category category);
|
||||
static std::string InsertCategoryPrefix(Category category, std::string input);
|
||||
static void Write(Category category, const char *fmt, ...);
|
||||
static void WriteLn(Category category, const char *fmt, ...);
|
||||
static std::string Format(const char *fmt, ...);
|
||||
static std::string VFormat(const char *fmt, va_list args);
|
||||
};
|
||||
#define Debug(...) ConsoleOutput::WriteLn(ConsoleOutput::Debug, __VA_ARGS__)
|
||||
#define Info(...) ConsoleOutput::WriteLn(ConsoleOutput::Info, __VA_ARGS__)
|
||||
#define Warning(...) ConsoleOutput::WriteLn(ConsoleOutput::Warning, __VA_ARGS__)
|
||||
#define Error(...) ConsoleOutput::WriteLn(ConsoleOutput::Error, __VA_ARGS__)
|
||||
#define Print(...) ConsoleOutput::Write(ConsoleOutput::None, __VA_ARGS__)
|
||||
#define PrintLn(...) ConsoleOutput::WriteLn(ConsoleOutput::None, __VA_ARGS__)
|
173
test.sh
173
test.sh
|
@ -1,11 +1,21 @@
|
|||
#!/bin/bash
|
||||
BLACK=0
|
||||
RED=1
|
||||
GREEN=2
|
||||
YELLOW=3
|
||||
BLUE=4
|
||||
MAGENTA=5
|
||||
CYAN=6
|
||||
WHITE=7
|
||||
GRAY=8
|
||||
DEFAULT=9
|
||||
bool_true() {
|
||||
[ "$1" = "true" ] 2>/dev/null || [ "$1" -ne 0 ] 2>/dev/null
|
||||
[ $? -ne 0 ] # Convert $? to 1 or 0 value
|
||||
[ $? -eq 0 ] # Convert $? to 1 or 0 value
|
||||
return $?
|
||||
}
|
||||
bool_false() {
|
||||
! bool_true
|
||||
! bool_true "$1"
|
||||
return $?
|
||||
}
|
||||
cmd_avail() {
|
||||
|
@ -14,15 +24,19 @@ cmd_avail() {
|
|||
tests=0
|
||||
failed=0
|
||||
succeeded=0
|
||||
failed_ids=()
|
||||
color=1
|
||||
tput_avail=0
|
||||
if cmd_avail tput; then
|
||||
tput_avail=1
|
||||
fi
|
||||
if bool_true $tput_avail; then
|
||||
COLORS=$(tput color 2>/dev/null)
|
||||
COLORS=$(tput colors 2>/dev/null)
|
||||
if [ $? -eq 0 ] && [ $COLORS -gt 2 ]; then
|
||||
color=1
|
||||
if [ $COLORS -lt 8 ]; then
|
||||
GRAY=9
|
||||
fi
|
||||
else
|
||||
color=0
|
||||
fi
|
||||
|
@ -30,6 +44,7 @@ fi
|
|||
usage() {
|
||||
cat << EOF
|
||||
$0 usage:
|
||||
-o|--output-dir <output directory>
|
||||
-p|--use-program <program path>
|
||||
Uses the specified already-compiled binary rather than compiling manually
|
||||
-i|--input-image <image path>
|
||||
|
@ -58,7 +73,9 @@ $0 usage:
|
|||
Disables color.
|
||||
-h|--help
|
||||
Shows this message.
|
||||
|
||||
-O|--reverse-dir <directory for reverse conversion files>
|
||||
Sets the directory for files that have been converted to PNG from BMX
|
||||
No effect when reverse conversion is disabled
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
@ -80,7 +97,9 @@ enable_dither=1
|
|||
enable_probe=1
|
||||
debug_flags=""
|
||||
outdir="testout"
|
||||
OPTIONS=$(getopt -o "b:hp:i:r:no:d:p:cCDRS" --long "help,use-program:,input-image:,output-bpp:,resize:,no-defaults,output-dir:,debug:,no-reverse,no-dither,no-compress,palette-file,no-generate-palette,no-probe,color,no-color" -- "$@")
|
||||
reverse_dir_set=0
|
||||
reversedir=""
|
||||
OPTIONS=$(getopt -o "b:hp:i:r:no:d:p:cCDRSO" --long "help,use-program:,input-image:,output-bpp:,resize:,no-defaults,output-dir:,debug:,no-reverse,no-dither,no-compress,palette-file,no-generate-palette,no-probe,color,no-color,reverse-dir" -- "$@")
|
||||
if [ $? != 0 ]; then
|
||||
echo "Getopt error."
|
||||
usage
|
||||
|
@ -88,6 +107,11 @@ fi
|
|||
eval set -- "$OPTIONS"
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-O|--reverse-dir)
|
||||
reversedir="$2"
|
||||
reverse_dir_set=1
|
||||
shift 2
|
||||
;;
|
||||
-o|--output-dir)
|
||||
outdir="$2"
|
||||
shift 2
|
||||
|
@ -162,15 +186,22 @@ while [ -n "$1" ]; do
|
|||
;;
|
||||
esac
|
||||
done
|
||||
if [ $generate_palette -ne 0 ]; then
|
||||
if bool_false $reverse_dir_set; then
|
||||
reversedir="$outdir/reverse"
|
||||
fi
|
||||
if bool_true $generate_palette; then
|
||||
palettes+=""
|
||||
fi
|
||||
if [ $enable_defaults -ne 0 ]; then
|
||||
if bool_true $enable_defaults; then
|
||||
images+=("TEST.png" "PACK.png" "CAT.jpg")
|
||||
bpps+=(1 2 4 8)
|
||||
resize+=("8x8" "16x16" "32x32" "64x64" "320x240" "640x480")
|
||||
resize+=("64x64" "320x240" "640x480")
|
||||
palettes+=("DPAL.BIN")
|
||||
fi
|
||||
if [ $prebuilt -eq 0 ]; then
|
||||
if bool_true $enable_reverse; then
|
||||
mkdir -p $reversedir
|
||||
fi
|
||||
if bool_false $prebuilt; then
|
||||
meson setup builddir
|
||||
meson compile -C builddir || exit $?
|
||||
fi
|
||||
|
@ -201,7 +232,7 @@ setfgcolor() {
|
|||
if bool_true "$tput_avail"; then
|
||||
tput setaf "$1"
|
||||
else
|
||||
printf "\033[0;3%sm" "$1"
|
||||
printf "\033[38;5;%sm" "$1"
|
||||
fi
|
||||
}
|
||||
setbgcolor() {
|
||||
|
@ -211,7 +242,7 @@ setbgcolor() {
|
|||
if bool_true "$tput_avail"; then
|
||||
tput setab "$1"
|
||||
else
|
||||
printf "\033[0;4%sm" "$1"
|
||||
printf "\033[48;5;%sm" "$1"
|
||||
fi
|
||||
}
|
||||
resetcolor() {
|
||||
|
@ -224,6 +255,10 @@ resetcolor() {
|
|||
printf "\033[0m"
|
||||
fi
|
||||
}
|
||||
extension() {
|
||||
len="$(printf "%s" "$1" | sed 's/[^.]*\.[^.]*/./g' | wc -c)"
|
||||
printf "%s" "$1" | cut -d. -f$(($len+1))
|
||||
}
|
||||
mkdir -p "$outdir"
|
||||
run() {
|
||||
converter="$1"
|
||||
|
@ -234,41 +269,65 @@ run() {
|
|||
shift
|
||||
reverse="$1"
|
||||
shift
|
||||
infile_for_id=$(basename $infile)
|
||||
outfile_for_id=$(basename $outfile)
|
||||
extra_flags_run=()
|
||||
if [ -n "$reverse" ]; then
|
||||
extra_flags_run+=( "$reverse" )
|
||||
extra_flags_probe=()
|
||||
if bool_true "$reverse"; then
|
||||
extra_flags_run+=( "-reverse" )
|
||||
else
|
||||
extra_flags_probe+=( "-reverse" )
|
||||
fi
|
||||
setfgcolor 2
|
||||
id="convert_${infile_for_id}_${outfile_for_id}"
|
||||
if [ -n "$reverse" ]; then
|
||||
id="${id}_reverse"
|
||||
fi
|
||||
setfgcolor $WHITE
|
||||
bold
|
||||
printf "Running: %s\n" "$converter $* -in $infile -out $outfile"
|
||||
printf "Running test %s\n" "$id"
|
||||
printf "Command: %s\n" "$converter -in $infile -out $outfile ${extra_flags_run[*]} $*"
|
||||
resetcolor
|
||||
setfgcolor 8
|
||||
setfgcolor $GRAY
|
||||
tests=$(($tests+1))
|
||||
"$converter" -in "$infile" -out "$outfile" "${extra_flags_run[@]}" "$@"
|
||||
if [ $? -ne 0 ]; then
|
||||
setfgcolor 1
|
||||
printf "Test failed.\n"
|
||||
printf "Test $id failed.\n"
|
||||
resetcolor
|
||||
failed=$(($failed+1))
|
||||
failed_ids+=($id)
|
||||
else
|
||||
setfgcolor $GREEN
|
||||
printf "Test $id succeeded!\n"
|
||||
resetcolor
|
||||
succeeded=$(($succeeded+1))
|
||||
fi
|
||||
resetcolor
|
||||
if [ $enable_probe -ne 0 ]; then
|
||||
setfgcolor 2
|
||||
id="probe_${outfile_for_id}"
|
||||
if [ -z "$reverse" ]; then
|
||||
id="${id}_pc"
|
||||
fi
|
||||
setfgcolor $BLUE
|
||||
bold
|
||||
printf "Running test %s\n" "$id"
|
||||
printf "Probing %s...\n" "$outfile"
|
||||
resetcolor
|
||||
setfgcolor 8
|
||||
"$converter" -in "$outfile" -probe "${extra_flags_run[@]}"
|
||||
setfgcolor $GRAY
|
||||
printf "Command: %s\n" "$converter -in $infile -probe ${extra_flags_probe[*]}"
|
||||
"$converter" -in "$outfile" -probe "${extra_flags_probe[@]}"
|
||||
resetcolor
|
||||
tests=$(($tests+1))
|
||||
if [ $? -ne 0 ]; then
|
||||
setfgcolor 1
|
||||
printf "Test failed.\n"
|
||||
setfgcolor $RED
|
||||
printf "Test $id failed.\n"
|
||||
resetcolor
|
||||
failed=$(($failed+1))
|
||||
failed_ids+=($id)
|
||||
else
|
||||
setfgcolor $GREEN
|
||||
printf "Test $id succeeded!\n"
|
||||
resetcolor
|
||||
succeeded=$(($succeeded+1))
|
||||
fi
|
||||
fi
|
||||
|
@ -280,11 +339,14 @@ for img in "${images[@]}"; do
|
|||
for palette in "${palettes[@]}"; do
|
||||
width="$(echo -n "$size" | cut -dx -f1)"
|
||||
height="$(echo -n "$size" | cut -dx -f2)"
|
||||
name="$(basename "$img" | sed 's/\.png$//' | sed 's/\.jpg$//' | sed 's/\.jpeg$//')"
|
||||
name="$(printf "%s.%sP.%sB" "$name" "$width" "$bpp")"
|
||||
ext="$(extension "$img")"
|
||||
ext_upper="$(printf "%s" "$ext" | tr '[:lower:]' '[:upper:]')"
|
||||
name="$(basename -s ".$ext" "$img")"
|
||||
name="$(printf "%s.%s.%sPX.%sB" "$name" "$ext_upper" "$width" "$bpp")"
|
||||
extraflags=()
|
||||
if [ -n "$palette" ]; then
|
||||
extraflags+=( "-palette-file" "$palette" )
|
||||
name+=".PL-$(basename -s ".$(extension "$palette")" "$palette" | tr '[:lower:]' '[:upper]')"
|
||||
fi
|
||||
if [ -n "$compressflag" ]; then
|
||||
if [ $enable_compression -eq 0 ]; then
|
||||
|
@ -293,14 +355,14 @@ for img in "${images[@]}"; do
|
|||
extraflags+=( "$compressflag" )
|
||||
name+=".C"
|
||||
fi
|
||||
run "$converter" "$img" "$outdir/$name.BMX" "" "${extraflags[@]}" "" -bpp "$bpp" -resize "$width" "$height" -border 15 0 15 -debug "$debug_flags"
|
||||
if [ $enable_dither -ne 0 ]; then
|
||||
run "$converter" "$img" "$outdir/$name.D.BMX" "" "${extraflags[@]}" "" -bpp "$bpp" -resize "$width" "$height" -dither -border 15 0 15 -debug "$debug_flags"
|
||||
run "$converter" "$img" "$outdir/$name.BMX" false "${extraflags[@]}" -bpp "$bpp" -resize "$width" "$height" -border 15 0 15 -debug "$debug_flags"
|
||||
if bool_true $enable_dither; then
|
||||
run "$converter" "$img" "$outdir/$name.D.BMX" false "${extraflags[@]}" -bpp "$bpp" -resize "$width" "$height" -dither -border 15 0 15 -debug "$debug_flags"
|
||||
fi
|
||||
if [ $enable_reverse -ne 0 ]; then
|
||||
run "$converter" "$outdir/$name.BMX" "$outdir/$name.PNG" -reverse "${extraflags[@]}" -resize "$width" "$height" -debug "$debug_flags"
|
||||
if [ $enable_dither -ne 0 ]; then
|
||||
run "$converter" "$outdir/$name.D.BMX" "$outdir/$name.D.PNG" -reverse "${extraflags[@]}" -resize "$width" "$height" -dither -debug "$debug_flags"
|
||||
if bool_true $enable_reverse; then
|
||||
run "$converter" "$outdir/$name.BMX" "$reversedir/$name.PNG" true "${extraflags[@]}" -resize "$width" "$height" -debug "$debug_flags"
|
||||
if bool_true $enable_dither; then
|
||||
run "$converter" "$outdir/$name.D.BMX" "$reversedir/$name.D.PNG" true "${extraflags[@]}" -resize "$width" "$height" -dither -debug "$debug_flags"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
@ -308,5 +370,52 @@ for img in "${images[@]}"; do
|
|||
done
|
||||
done
|
||||
done
|
||||
printf "%s total test cases, %s failed, %s succeeded, %s%% succeeded and %s%% failed.\n" "$tests" "$failed" "$succeeded" "$((($succeeded*100)/$tests))" "$((($failed*100)/$tests))"
|
||||
badcolor=$RED
|
||||
goodcolor=$GREEN
|
||||
okcolor=$YELLOW
|
||||
success_good=90
|
||||
success_ok=50
|
||||
percent_out_of_tests() {
|
||||
if [ "$tests" -eq 0 ]; then
|
||||
printf "100"
|
||||
else
|
||||
printf "%s" "$((($1*100)/$tests))"
|
||||
fi
|
||||
}
|
||||
invert_percent() {
|
||||
printf "%s" "$((100-$1))"
|
||||
}
|
||||
success_percent="$(percent_out_of_tests $succeeded)"
|
||||
failed_percent="$(percent_out_of_tests $failed)"
|
||||
set_color_by_good_percentage() {
|
||||
if [ "$1" -ge $success_good ]; then
|
||||
setfgcolor "$goodcolor"
|
||||
elif [ "$1" -ge $success_ok ]; then
|
||||
setfgcolor "$okcolor"
|
||||
else
|
||||
setfgcolor "$badcolor"
|
||||
fi
|
||||
}
|
||||
set_color_by_bad_percentage() {
|
||||
set_color_by_good_percentage "$(invert_percent $1)"
|
||||
}
|
||||
bold
|
||||
setfgcolor $WHITE
|
||||
printf "%s total test cases, " "$tests"
|
||||
set_color_by_bad_percentage "$failed_percent"
|
||||
printf "%s failed (%s%%) " "$failed" "$failed_percent"
|
||||
setfgcolor $WHITE
|
||||
printf "and "
|
||||
set_color_by_good_percentage "$success_percent"
|
||||
printf "%s succeeded (%s%%)." "$succeeded" "$success_percent"
|
||||
resetcolor
|
||||
printf "\n"
|
||||
if [ "$failed" -gt 0 ]; then
|
||||
setfgcolor $RED
|
||||
printf "Failing tests:\n"
|
||||
for test in "${failed_ids[@]}"; do
|
||||
printf "Test '%s'\n"
|
||||
done
|
||||
resetcolor
|
||||
fi
|
||||
cd "$oldpwd"
|
||||
|
|
Loading…
Reference in a new issue