Various improvements

This commit is contained in:
Zachary Hall 2023-12-07 13:04:14 -08:00
parent 1b93f5d09d
commit 37b80d3624
7 changed files with 474 additions and 83 deletions

57
.vscode/settings.json vendored
View file

@ -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"
}
}

View file

@ -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);

View file

@ -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

View file

@ -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
View 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
View 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
View file

@ -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"