729 lines
18 KiB
C++
729 lines
18 KiB
C++
#include <cstdint>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <locale>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
static const char characterHeight{13};
|
|
static constexpr char characterWidth{6};
|
|
static const std::map<std::string, std::vector<char>> charToBitmap = {
|
|
{" ", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0
|
|
}},
|
|
{"▁", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▂", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▃", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▄", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▅", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▆", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▇", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
}},
|
|
{"▇", {
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▉", {
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0,
|
|
1, 1, 1, 1, 1, 0
|
|
}},
|
|
{"▊", {
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0,
|
|
1, 1, 1, 1, 0, 0
|
|
}},
|
|
{"▌", {
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0
|
|
}},
|
|
{"▍", {
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0,
|
|
1, 1, 0, 0, 0, 0
|
|
}},
|
|
{"▏", {
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0
|
|
}},
|
|
{"▐", {
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1
|
|
}},
|
|
{"▀", {
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0
|
|
}},
|
|
{"░", {
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 0, 1, 0, 1, 0
|
|
}},
|
|
{"▒", {
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 0, 1, 0, 1, 0
|
|
}},
|
|
{"▓", {
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 1, 0, 1, 0, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 0, 1, 0, 1, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 1, 0, 1, 0, 1
|
|
}},
|
|
{"▔", {
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0
|
|
}},
|
|
{"▕", {
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 0, 1
|
|
}},
|
|
{"▖", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0
|
|
}},
|
|
{"▗", {
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1
|
|
}},
|
|
{"▘", {
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0
|
|
}},
|
|
{"▝", {
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0
|
|
}},
|
|
{"▙", {
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}},
|
|
{"▚", {
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1
|
|
}},
|
|
{"▛", {
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0
|
|
}},
|
|
{"▜", {
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1
|
|
}},
|
|
{"▞", {
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0,
|
|
1, 1, 1, 0, 0, 0
|
|
}},
|
|
{"▟", {
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
0, 0, 0, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1
|
|
}}
|
|
};
|
|
|
|
#pragma pack(push, 1)
|
|
struct BITMAPINFOHEADER {
|
|
std::uint32_t size; // size of info header (should be 40).
|
|
std::uint32_t width; // horizontal width of bitmap in pixels.
|
|
std::uint32_t height; // vertical height of bitmap in pixels.
|
|
std::uint16_t planes; // number of planes.
|
|
std::uint16_t bitCount; // bits per pixel used to store palette entry info.
|
|
std::uint32_t compression; // type of compression.
|
|
std::uint32_t sizeImage; // size of image
|
|
std::uint32_t xPixelsPerMeter; // horizontal resolution in pixels/meter.
|
|
std::uint32_t yPixelsPerMeter; // vertical resolution in pixels/meter.
|
|
std::uint32_t colorsUsed; // Number of actually used colors.
|
|
std::uint32_t importantColors; // Number of important colors (0=all)
|
|
};
|
|
struct BITMAPFILEHEADER { // Total: 54 bytes
|
|
std::uint16_t type; // Magic identifier: 0x4d42
|
|
std::uint32_t size; // File size in bytes
|
|
std::uint16_t reserved1; // Not used
|
|
std::uint16_t reserved2; // Not used
|
|
std::uint32_t offset; // Offset to image data in bytes from beginning of file (54 bytes)
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
struct Color
|
|
{
|
|
uint8_t r{0};
|
|
uint8_t g{0};
|
|
uint8_t b{0};
|
|
|
|
bool operator==(const Color& other) const
|
|
{
|
|
return ((other.r == r) && (other.g == g) && (other.b == b));
|
|
}
|
|
};
|
|
|
|
using Bitmap = std::vector<Color>;
|
|
|
|
struct Image
|
|
{
|
|
std::uint32_t width{0};
|
|
std::uint32_t height{0};
|
|
Bitmap bitmap;
|
|
};
|
|
|
|
int LoadBMP(const char location[], Image& result)
|
|
{
|
|
BITMAPFILEHEADER bmpHeader{};
|
|
BITMAPINFOHEADER bmpInfo{};
|
|
std::ifstream file(location, std::ios::binary);
|
|
if(!file)
|
|
{
|
|
std::cerr << "Failure to open bitmap file.\n";
|
|
return 1;
|
|
}
|
|
file.seekg(0, file.beg);
|
|
file.read(reinterpret_cast<char*>(&bmpHeader), sizeof(BITMAPFILEHEADER));
|
|
file.read(reinterpret_cast<char*>(&bmpInfo), sizeof(BITMAPINFOHEADER));
|
|
if(bmpHeader.type != 0x4D42)
|
|
{
|
|
std::cerr << "File \"" << location << "\" isn't a bitmap file\n";
|
|
return 2;
|
|
}
|
|
const auto width = bmpInfo.width;
|
|
const auto height = bmpInfo.height;
|
|
result.width = width;
|
|
result.height = height;
|
|
std::uint32_t row_padded = (width * 3 + 3) & (~3);
|
|
std::uint32_t y{0};
|
|
file.seekg(bmpHeader.offset, file.beg);
|
|
for (int y = 0; y < height; ++y)
|
|
{
|
|
std::uint8_t data[row_padded];
|
|
file.read(reinterpret_cast<char*>(&data), sizeof(std::uint8_t) * row_padded);
|
|
std::uint32_t x{0};
|
|
for (std::uint32_t b = 0; b < (width * 3); b += 3)
|
|
{
|
|
result.bitmap.insert(result.bitmap.begin(), Color{
|
|
data[b+2],
|
|
data[b+1],
|
|
data[b]
|
|
});
|
|
x++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void usage(const std::string& progName)
|
|
{
|
|
std::cout << "Usage: " << progName << " [input filename]" << std::endl;
|
|
}
|
|
|
|
Color getXY(const Image& img, std::uint32_t x, std::uint32_t y)
|
|
{
|
|
const std::uint32_t i = (img.width * y) + x;
|
|
if (i > img.bitmap.size())
|
|
{
|
|
throw std::runtime_error(
|
|
"Pixel index out of range: " + std::to_string(i)
|
|
+ " x=" + std::to_string(x)
|
|
+ ", y=" + std::to_string(y)
|
|
);
|
|
}
|
|
return img.bitmap[i];
|
|
}
|
|
|
|
void splitImage(const Image& input, std::vector<Image>& output, uint32_t& cols, uint32_t& rows)
|
|
{
|
|
const auto numCols = input.width / characterWidth;
|
|
const auto numRows = input.height / characterHeight;
|
|
rows = numRows;
|
|
cols = numCols;
|
|
for (std::uint32_t cy = 0; cy < numRows; ++cy)
|
|
{
|
|
for (std::uint32_t cx = numCols; cx != 0; --cx)
|
|
{
|
|
std::uint32_t i_x_start = cx * characterWidth;
|
|
std::uint32_t i_x_end = (cx + 1) * characterWidth;
|
|
if (i_x_end > input.width) i_x_end = input.width;
|
|
std::uint32_t i_y_start = cy * characterHeight;
|
|
std::uint32_t i_y_end = (cy + 1) * characterHeight;
|
|
if (i_y_end > input.height) i_y_end = input.height;
|
|
Image c;
|
|
c.width = characterWidth;
|
|
c.height = characterHeight;
|
|
std::uint32_t cbx{0};
|
|
std::uint32_t cby{0};
|
|
for (std::uint32_t iy = i_y_start; iy != i_y_end; ++iy)
|
|
{
|
|
for (std::uint32_t ix = i_x_start; ix < i_x_end; ++ix)
|
|
{
|
|
c.bitmap.emplace_back(getXY(input, ix, iy));
|
|
}
|
|
cby++;
|
|
}
|
|
output.emplace_back(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
void showImage(const Image& image)
|
|
{
|
|
for (std::uint32_t y = 0 ; y < image.height ; ++y)
|
|
{
|
|
for (std::uint32_t x = 1; x < image.width; ++x)
|
|
{
|
|
const auto c = getXY(image, x, y);
|
|
char r = c.r;
|
|
char g = c.g;
|
|
char b = c.b;
|
|
std::cout << "\x1b[48;2;" << c.r+0 << ";" << c.g+0 << ";" << c.b+0 << "m ";
|
|
}
|
|
std::cout << "\x1b[0m" << std::endl;
|
|
}
|
|
std::cout << "\x1b[0m" << std::endl;
|
|
}
|
|
|
|
|
|
std::vector<char> toMask(const Image& image, const Color& alpha)
|
|
{
|
|
std::vector<char> result;
|
|
for (const auto c: image.bitmap)
|
|
{
|
|
result.emplace_back(c == alpha ? 0 : 1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
float percentMatch(const std::vector<char>& a, const std::vector<char>& b)
|
|
{
|
|
std::uint32_t matches{0};
|
|
std::uint32_t i{0};
|
|
for (const auto c: a)
|
|
{
|
|
if (c == b[i]) matches++;
|
|
i++;
|
|
}
|
|
return (static_cast<float>(matches) / static_cast<float>(a.size())) * 100.0f;
|
|
}
|
|
|
|
std::string findMatch(const Image& image, const Color& alpha)
|
|
{
|
|
const auto imageMask = toMask(image, alpha);
|
|
float maxPercent{0.0f};
|
|
std::string result;
|
|
for (const auto ctb: charToBitmap)
|
|
{
|
|
const float pm = percentMatch(imageMask, ctb.second);
|
|
if (pm > maxPercent)
|
|
{
|
|
result = ctb.first;
|
|
maxPercent = pm;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
setlocale(LC_CTYPE,"");
|
|
std::string progName(argv[0]);
|
|
bool colorDumpMode{false};
|
|
if (argc < 2)
|
|
{
|
|
std::cerr << "Invalid number of arguments." << std::endl;
|
|
usage(progName);
|
|
return 1;
|
|
}
|
|
std::string bitmapFileName = argv[1];
|
|
if (bitmapFileName == "-c")
|
|
{
|
|
if (argc < 3)
|
|
{
|
|
std::cerr << "Invalid number of arguments." << std::endl;
|
|
usage(progName);
|
|
return 1;
|
|
}
|
|
bitmapFileName = argv[2];
|
|
colorDumpMode = true;
|
|
}
|
|
std::cout << bitmapFileName << std::endl;
|
|
Image image;
|
|
const int result = LoadBMP(bitmapFileName.c_str(), image);
|
|
if (result != 0)
|
|
{
|
|
std::cerr << "Could not parse bitmap, error " << result << std::endl;
|
|
return result;
|
|
}
|
|
if (colorDumpMode)
|
|
{
|
|
showImage(image);
|
|
}
|
|
else
|
|
{
|
|
std::vector<Image> charBitmaps;
|
|
std::uint32_t cols{0};
|
|
std::uint32_t rows{0};
|
|
splitImage(image, charBitmaps, cols, rows);
|
|
std::cout << "Parsed " << charBitmaps.size() << " characters." << std::endl;
|
|
std::cout << "Cols: " << cols << " Rows: " << rows << std::endl;
|
|
std::uint32_t i{0};
|
|
for (const auto charBitmap: charBitmaps)
|
|
{
|
|
if ((i % cols) == 0) std::cout << std::endl;
|
|
std::cout << findMatch(charBitmap, Color{0, 0, 0});
|
|
i++;
|
|
}
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
|