parent
3373e02e4c
commit
dedaa1b7c2
1 changed files with 53 additions and 45 deletions
170
src/tiv.cpp
170
src/tiv.cpp
|
@ -41,20 +41,24 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// This #define tells CImg that we use the library without any display options --
|
// This #define tells CImg that we use the library without any display options
|
||||||
// just for loading images.
|
// -- just for loading images.
|
||||||
#define cimg_display 0
|
#define cimg_display 0
|
||||||
#include "CImg.h"
|
#include "CImg.h"
|
||||||
|
|
||||||
#ifdef _POSIX_VERSION
|
#ifdef _POSIX_VERSION
|
||||||
// Console output size detection
|
// Console output size detection
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
// Error explanation, for some reason
|
||||||
|
#include <cstring>
|
||||||
// Exit codes
|
// Exit codes
|
||||||
#include <sysexits.h>
|
#include <sysexits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
// Error explanation
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
// Following codes copied from /usr/include/sysexits.h,
|
// Following codes copied from /usr/include/sysexits.h,
|
||||||
// license: https://opensource.org/license/BSD-3-clause/
|
// license: https://opensource.org/license/BSD-3-clause/
|
||||||
|
@ -89,8 +93,8 @@ constexpr int GRAYSCALE_STEPS[GRAYSCALE_STEP_COUNT] = {
|
||||||
0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e, 0x58, 0x62, 0x6c, 0x76,
|
0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e, 0x58, 0x62, 0x6c, 0x76,
|
||||||
0x80, 0x8a, 0x94, 0x9e, 0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee};
|
0x80, 0x8a, 0x94, 0x9e, 0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee};
|
||||||
|
|
||||||
// An interleaved map of 4x8 bit character bitmaps (each hex digit represents a row)
|
// An interleaved map of 4x8 bit character bitmaps (each hex digit represents a
|
||||||
// to the corresponding unicode character code point.
|
// row) to the corresponding unicode character code point.
|
||||||
constexpr unsigned int BITMAPS[] = {
|
constexpr unsigned int BITMAPS[] = {
|
||||||
0x00000000, 0x00a0,
|
0x00000000, 0x00a0,
|
||||||
|
|
||||||
|
@ -228,8 +232,8 @@ typedef std::function<unsigned char(int, int, int)> GetPixelFunction;
|
||||||
|
|
||||||
// Return a CharData struct with the given code point and corresponding averag
|
// Return a CharData struct with the given code point and corresponding averag
|
||||||
// fg and bg colors.
|
// fg and bg colors.
|
||||||
CharData createCharData(GetPixelFunction get_pixel, int x0,
|
CharData createCharData(GetPixelFunction get_pixel, int x0, int y0,
|
||||||
int y0, int codepoint, int pattern) {
|
int codepoint, int pattern) {
|
||||||
CharData result;
|
CharData result;
|
||||||
result.codePoint = codepoint;
|
result.codePoint = codepoint;
|
||||||
int fg_count = 0;
|
int fg_count = 0;
|
||||||
|
@ -275,8 +279,8 @@ CharData createCharData(GetPixelFunction get_pixel, int x0,
|
||||||
* @param flags
|
* @param flags
|
||||||
* @return CharData
|
* @return CharData
|
||||||
*/
|
*/
|
||||||
CharData findCharData(GetPixelFunction get_pixel, int x0,
|
CharData findCharData(GetPixelFunction get_pixel, int x0, int y0,
|
||||||
int y0, const int &flags) {
|
const int &flags) {
|
||||||
int min[3] = {255, 255, 255};
|
int min[3] = {255, 255, 255};
|
||||||
int max[3] = {0};
|
int max[3] = {0};
|
||||||
std::map<long, int> count_per_color;
|
std::map<long, int> count_per_color;
|
||||||
|
@ -479,8 +483,8 @@ void emitCodepoint(int codepoint) {
|
||||||
|
|
||||||
void emit_image(const cimg_library::CImg<unsigned char> &image,
|
void emit_image(const cimg_library::CImg<unsigned char> &image,
|
||||||
const int &flags) {
|
const int &flags) {
|
||||||
|
GetPixelFunction get_pixel = [&](int x, int y,
|
||||||
GetPixelFunction get_pixel = [&](int x, int y, int channel) -> unsigned char {
|
int channel) -> unsigned char {
|
||||||
return image(x, y, 0, channel);
|
return image(x, y, 0, channel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -565,11 +569,84 @@ enum Mode { AUTO, THUMBNAILS, FULL_SIZE };
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
std::ios::sync_with_stdio(false); // apparently makes printing faster
|
std::ios::sync_with_stdio(false); // apparently makes printing faster
|
||||||
|
bool detectSize = true;
|
||||||
|
|
||||||
// Platform-specific implementations for determining console size, better
|
// Platform-specific implementations for determining console size, better
|
||||||
// implementations are welcome Fallback sizes when unsuccesful
|
// implementations are welcome Fallback sizes when unsuccesful
|
||||||
int maxWidth = 80;
|
int maxWidth = 80;
|
||||||
int maxHeight = 24;
|
int maxHeight = 24;
|
||||||
|
|
||||||
|
// Reading input
|
||||||
|
char flags = 0; // bitwise representation of flags,
|
||||||
|
// see https://stackoverflow.com/a/14295472
|
||||||
|
Mode mode = AUTO; // either THUMBNAIL or FULL_SIZE
|
||||||
|
int columns = 3;
|
||||||
|
|
||||||
|
std::vector<std::string> file_names;
|
||||||
|
int ret = EX_OK; // The return code for the program
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
emit_usage();
|
||||||
|
return EX_USAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
std::string arg(argv[i]);
|
||||||
|
if (arg == "-0") {
|
||||||
|
flags |= FLAG_NOOPT;
|
||||||
|
} else if (arg == "-c") {
|
||||||
|
if (i < argc - 1) {
|
||||||
|
columns = std::stoi(argv[++i]);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: -c requires a number" << std::endl;
|
||||||
|
ret = EX_USAGE;
|
||||||
|
}
|
||||||
|
} else if (arg == "-d" || arg == "--dir") {
|
||||||
|
mode = THUMBNAILS;
|
||||||
|
} else if (arg == "-f" || arg == "--full") {
|
||||||
|
mode = FULL_SIZE;
|
||||||
|
} else if (arg == "-w") {
|
||||||
|
if (i < argc - 1) {
|
||||||
|
maxWidth = 4 * std::stoi(argv[++i]), detectSize = false;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: -w requires a number" << std::endl;
|
||||||
|
ret = EX_USAGE;
|
||||||
|
}
|
||||||
|
} else if (arg == "-h") {
|
||||||
|
if (i < argc - 1)
|
||||||
|
maxHeight = 8 * std::stoi(argv[++i]), detectSize = false;
|
||||||
|
else
|
||||||
|
printUsage(); // people might confuse this with help
|
||||||
|
} else if (arg == "--256" || arg == "-2" || arg == "-256") {
|
||||||
|
flags |= FLAG_MODE_256;
|
||||||
|
} else if (arg == "--help" || arg == "-help") {
|
||||||
|
emit_usage();
|
||||||
|
} else if (arg == "-x") {
|
||||||
|
flags |= FLAG_TELETEXT;
|
||||||
|
} else if (arg[0] == '-') {
|
||||||
|
std::cerr << "Error: Unrecognized argument: " << arg << std::endl;
|
||||||
|
ret = EX_USAGE;
|
||||||
|
} else {
|
||||||
|
// Arguments that will be displayed
|
||||||
|
if (std::filesystem::is_directory(arg)) {
|
||||||
|
for (auto &p : std::filesystem::directory_iterator(arg))
|
||||||
|
if (std::filesystem::is_regular_file(p.path()))
|
||||||
|
file_names.push_back(p.path().string());
|
||||||
|
} else {
|
||||||
|
// Check if file can be opened, @TODO find better way
|
||||||
|
std::ifstream fin(arg.c_str());
|
||||||
|
if (fin) {
|
||||||
|
file_names.push_back(arg);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Cannot open '" << arg
|
||||||
|
<< "', permission issue?" << std::endl;
|
||||||
|
ret = EX_NOINPUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectSize) {
|
||||||
#ifdef _POSIX_VERSION
|
#ifdef _POSIX_VERSION
|
||||||
struct winsize w;
|
struct winsize w;
|
||||||
// If redirecting STDOUT to one file ( col or row == 0, or the previous
|
// If redirecting STDOUT to one file ( col or row == 0, or the previous
|
||||||
|
@ -591,8 +668,8 @@ int main(int argc, char *argv[]) {
|
||||||
maxWidth = w.dwSize.X * 4;
|
maxWidth = w.dwSize.X * 4;
|
||||||
maxHeight = w.dwSize.Y * 8;
|
maxHeight = w.dwSize.Y * 8;
|
||||||
} else {
|
} else {
|
||||||
std::cerr
|
std::cerr << "Warning: failed to determine most reasonable size: "
|
||||||
<< "Warning: failed to determine most reasonable size: Error code"
|
"Error code"
|
||||||
<< GetLastError() << ", defaulting to 80x24" << std::endl;
|
<< GetLastError() << ", defaulting to 80x24" << std::endl;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -600,75 +677,6 @@ int main(int argc, char *argv[]) {
|
||||||
"unrecognized system, defaulting to 80x24"
|
"unrecognized system, defaulting to 80x24"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reading input
|
|
||||||
char flags = 0; // bitwise representation of flags,
|
|
||||||
// see https://stackoverflow.com/a/14295472
|
|
||||||
Mode mode = AUTO; // either THUMBNAIL or FULL_SIZE
|
|
||||||
int columns = 3;
|
|
||||||
|
|
||||||
std::vector<std::string> file_names;
|
|
||||||
int ret = EX_OK; // The return code for the program
|
|
||||||
|
|
||||||
if (argc <= 1) {
|
|
||||||
emit_usage();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
std::string arg(argv[i]);
|
|
||||||
if (arg == "-0") {
|
|
||||||
flags |= FLAG_NOOPT;
|
|
||||||
} else if (arg == "-c") {
|
|
||||||
if (i < argc - 1) {
|
|
||||||
columns = std::stoi(argv[++i]);
|
|
||||||
} else {
|
|
||||||
std::cerr << "Error: -c requires a number" << std::endl;
|
|
||||||
ret = EX_USAGE;
|
|
||||||
}
|
|
||||||
} else if (arg == "-d" || arg == "--dir") {
|
|
||||||
mode = THUMBNAILS;
|
|
||||||
} else if (arg == "-f" || arg == "--full") {
|
|
||||||
mode = FULL_SIZE;
|
|
||||||
} else if (arg == "-w") {
|
|
||||||
if (i < argc - 1) {
|
|
||||||
maxWidth = 4 * std::stoi(argv[++i]);
|
|
||||||
} else {
|
|
||||||
std::cerr << "Error: -w requires a number" << std::endl;
|
|
||||||
ret = EX_USAGE;
|
|
||||||
}
|
|
||||||
} else if (arg == "-h") {
|
|
||||||
if (i < argc - 1)
|
|
||||||
maxHeight = 8 * std::stoi(argv[++i]);
|
|
||||||
else
|
|
||||||
emit_usage();
|
|
||||||
} else if (arg == "--256" || arg == "-2" || arg == "-256") {
|
|
||||||
flags |= FLAG_MODE_256;
|
|
||||||
} else if (arg == "--help" || arg == "-help") {
|
|
||||||
emit_usage();
|
|
||||||
} else if (arg == "-x") {
|
|
||||||
flags |= FLAG_TELETEXT;
|
|
||||||
} else if (arg[0] == '-') {
|
|
||||||
std::cerr << "Error: Unrecognized argument: " << arg << std::endl;
|
|
||||||
ret = EX_USAGE;
|
|
||||||
} else {
|
|
||||||
// Arguments that will be displayed
|
|
||||||
if (std::filesystem::is_directory(arg)) {
|
|
||||||
for (auto &p : std::filesystem::directory_iterator(arg))
|
|
||||||
if (std::filesystem::is_regular_file(p.path()))
|
|
||||||
file_names.push_back(p.path().string());
|
|
||||||
} else {
|
|
||||||
// Check if file can be opened
|
|
||||||
std::ifstream fin(arg.c_str());
|
|
||||||
if (fin) {
|
|
||||||
file_names.push_back(arg);
|
|
||||||
} else {
|
|
||||||
std::cerr << "Error: Cannot open '" << arg
|
|
||||||
<< "', permission issue?" << std::endl;
|
|
||||||
ret = EX_NOINPUT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == FULL_SIZE || (mode == AUTO && file_names.size() == 1)) {
|
if (mode == FULL_SIZE || (mode == AUTO && file_names.size() == 1)) {
|
||||||
|
|
Loading…
Reference in a new issue