Added gradient (charmap) module and other stuff
Like uh, UTF-8 encoding/decoding, some fixes in `calc_brightness`, some changes in `c_fatal` (it now accepts formatting) and some other things I of course forgot. Oh yeah, and module now can signal that something went horrubly wrong and die. Yay!
This commit is contained in:
parent
283422c62d
commit
fa72c81f70
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ CLIBS := -lm
|
||||||
INCLUDES := -Isrc
|
INCLUDES := -Isrc
|
||||||
OBJECTS := obj/stb_image.o obj/stb_image_resize.o \
|
OBJECTS := obj/stb_image.o obj/stb_image_resize.o \
|
||||||
obj/colors.o obj/args.o obj/image.o obj/commons.o \
|
obj/colors.o obj/args.o obj/image.o obj/commons.o \
|
||||||
obj/mod_blocks.o obj/mod_braille.o
|
obj/mod_blocks.o obj/mod_braille.o obj/mod_charmap.o
|
||||||
VERSION := "v-git-$(shell git rev-parse --short HEAD)"
|
VERSION := "v-git-$(shell git rev-parse --short HEAD)"
|
||||||
|
|
||||||
all: lib yaitaa
|
all: lib yaitaa
|
||||||
|
|
15
src/args.c
15
src/args.c
|
@ -9,6 +9,7 @@
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "mod_blocks.h"
|
#include "mod_blocks.h"
|
||||||
#include "mod_braille.h"
|
#include "mod_braille.h"
|
||||||
|
#include "mod_charmap.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int value;
|
int value;
|
||||||
|
@ -32,7 +33,7 @@ const asc_handler_t asc_handlers[ASC_MOD_ENDL + 1] = {
|
||||||
{ ASC_MOD_GRADIENT,
|
{ ASC_MOD_GRADIENT,
|
||||||
{ "g", "grd", "gradient", NULL },
|
{ "g", "grd", "gradient", NULL },
|
||||||
"Gradient of characters. No matching at all",
|
"Gradient of characters. No matching at all",
|
||||||
NULL, NULL },
|
mod_cmap_prepare, mod_cmap_main },
|
||||||
{ ASC_MOD_BRUTEFORCE,
|
{ ASC_MOD_BRUTEFORCE,
|
||||||
{ "f", "guess", "bruteforce", NULL },
|
{ "f", "guess", "bruteforce", NULL },
|
||||||
"Looking for best possible character",
|
"Looking for best possible character",
|
||||||
|
@ -100,6 +101,7 @@ void usage(int argc, char **argv)
|
||||||
fprintf(stderr, "-O FILE\t\tOutput file. Default: - (stdout)\n");
|
fprintf(stderr, "-O FILE\t\tOutput file. Default: - (stdout)\n");
|
||||||
fprintf(stderr, "-W WIDTH\tOutput width (in characters)\n");
|
fprintf(stderr, "-W WIDTH\tOutput width (in characters)\n");
|
||||||
fprintf(stderr, "-H HEIGHT\tOutput height (in characters)\n");
|
fprintf(stderr, "-H HEIGHT\tOutput height (in characters)\n");
|
||||||
|
fprintf(stderr, "-C CHARSET\tList of characters. Used in some modes\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "-M MODE\t\tOutput mode\n");
|
fprintf(stderr, "-M MODE\t\tOutput mode\n");
|
||||||
fprintf(stderr, "-S STYLE\tStyle (palette)\n");
|
fprintf(stderr, "-S STYLE\tStyle (palette)\n");
|
||||||
|
@ -147,9 +149,9 @@ int parse_args(int argc, char **argv, asc_args_t *args)
|
||||||
args->charset = " .'-*+$@";
|
args->charset = " .'-*+$@";
|
||||||
int c;
|
int c;
|
||||||
#ifdef DISABLE_LOGGING
|
#ifdef DISABLE_LOGGING
|
||||||
while ((c = getopt(argc, argv, "hdVW:H:M:S:F:P:O:")) != -1)
|
while ((c = getopt(argc, argv, "hdVC:W:H:M:S:F:P:O:")) != -1)
|
||||||
#else
|
#else
|
||||||
while ((c = getopt(argc, argv, "vhdVW:H:M:S:F:P:O:")) != -1)
|
while ((c = getopt(argc, argv, "vhdVC:W:H:M:S:F:P:O:")) != -1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
|
@ -168,6 +170,9 @@ int parse_args(int argc, char **argv, asc_args_t *args)
|
||||||
case 'd':
|
case 'd':
|
||||||
args->dither = true;
|
args->dither = true;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
args->charset = optarg;
|
||||||
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
if ((args->width = atoi(optarg)) < 0)
|
if ((args->width = atoi(optarg)) < 0)
|
||||||
{
|
{
|
||||||
|
@ -282,6 +287,10 @@ int prepare_state(int argc, char **argv, asc_args_t args, asc_state_t *state)
|
||||||
LOG("Image size: %dx%d",
|
LOG("Image size: %dx%d",
|
||||||
state->source_image->width, state->source_image->height);
|
state->source_image->width, state->source_image->height);
|
||||||
|
|
||||||
|
state->image = state->source_image;
|
||||||
|
|
||||||
|
state->userdata = NULL;
|
||||||
|
|
||||||
// Palette configuration
|
// Palette configuration
|
||||||
switch (args.out_style)
|
switch (args.out_style)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,11 +68,12 @@ typedef struct {
|
||||||
image_t *source_image;
|
image_t *source_image;
|
||||||
image_t *image;
|
image_t *image;
|
||||||
palette_t *palette;
|
palette_t *palette;
|
||||||
|
void *userdata;
|
||||||
FILE *out_file;
|
FILE *out_file;
|
||||||
} asc_state_t;
|
} asc_state_t;
|
||||||
|
|
||||||
typedef void (*asc_module_initializer_fn)(asc_state_t *state);
|
typedef bool (*asc_module_initializer_fn)(asc_state_t *state);
|
||||||
typedef void (*asc_module_handler_fn)(asc_state_t state);
|
typedef bool (*asc_module_handler_fn)(asc_state_t state);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int id;
|
int id;
|
||||||
|
|
|
@ -141,7 +141,7 @@ void make_pal256(palette_t *dst, palette_t ansi)
|
||||||
|
|
||||||
float calc_brightness(rgba8 c)
|
float calc_brightness(rgba8 c)
|
||||||
{
|
{
|
||||||
return 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b;
|
return (0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) / 255.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load_palette_gpl(palette_t *pal, FILE *fp)
|
bool load_palette_gpl(palette_t *pal, FILE *fp)
|
||||||
|
|
135
src/commons.c
135
src/commons.c
|
@ -44,9 +44,14 @@ void _log(const char *fmt, ...)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void c_fatal(int code, const char *reason)
|
void c_fatal(int code, const char *reason, ...)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: %s\n", reason);
|
fprintf(stderr, "Error: ");
|
||||||
|
va_list args;
|
||||||
|
va_start(args, reason);
|
||||||
|
vfprintf(stderr, reason, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,3 +69,129 @@ palette_t *get_palette_by_id(asc_style_t stl)
|
||||||
}
|
}
|
||||||
return pal;
|
return pal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From: https://github.com/raysan5/raylib/blob/e5ee69a/src/rtext.c#L1729
|
||||||
|
__attribute__((annotate("oclint:suppress[bitwise operator in conditional]")))
|
||||||
|
__attribute__((annotate("oclint:suppress[high cyclomatic complexity]")))
|
||||||
|
__attribute__((annotate("oclint:suppress[high npath complexity]")))
|
||||||
|
__attribute__((annotate("oclint:suppress[high ncss method]")))
|
||||||
|
__attribute__((annotate("oclint:suppress[long method]")))
|
||||||
|
int get_codepoint(char *text, int *processed)
|
||||||
|
{
|
||||||
|
int code = 0;
|
||||||
|
int octet = (unsigned char)(text[0]);
|
||||||
|
*processed = 1;
|
||||||
|
|
||||||
|
if (octet <= 0x7f)
|
||||||
|
{
|
||||||
|
code = text[0];
|
||||||
|
}
|
||||||
|
else if ((octet & 0xe0) == 0xc0)
|
||||||
|
{
|
||||||
|
unsigned char octet1 = text[1];
|
||||||
|
if ((octet1 == '\0') || ((octet1 >> 6) != 2))
|
||||||
|
{ *processed = 2; return 0; }
|
||||||
|
if ((octet >= 0xc2) && (octet <= 0xdf))
|
||||||
|
{
|
||||||
|
code = ((octet & 0x1f) << 6) | (octet1 & 0x3f);
|
||||||
|
*processed = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((octet & 0xf0) == 0xe0)
|
||||||
|
{
|
||||||
|
unsigned char octet1 = text[1];
|
||||||
|
unsigned char octet2 = '\0';
|
||||||
|
if ((octet1 == '\0') || ((octet1 >> 6) != 2))
|
||||||
|
{ *processed = 2; return 0; }
|
||||||
|
octet2 = text[2];
|
||||||
|
if ((octet2 == '\0') || ((octet2 >> 6) != 2))
|
||||||
|
{ *processed = 3; return 0; }
|
||||||
|
if (((octet == 0xe0) && !((octet1 >= 0xa0) && (octet1 < 0xbf))) ||
|
||||||
|
((octet == 0xed) && !((octet1 >= 0x80) && (octet1 <= 0x9f))))
|
||||||
|
{ *processed = 2; return 0; }
|
||||||
|
if ((octet >= 0xe0) && (octet <= 0xef))
|
||||||
|
{ code = ((octet & 0xf) << 12) | ((octet1 & 0x3f) << 6) | (octet2 & 0x3f);
|
||||||
|
*processed = 3; }
|
||||||
|
}
|
||||||
|
else if ((octet & 0xf8) == 0xf0)
|
||||||
|
{
|
||||||
|
if (octet > 0xf4) return 0;
|
||||||
|
unsigned char octet1 = text[1];
|
||||||
|
unsigned char octet2 = '\0';
|
||||||
|
unsigned char octet3 = '\0';
|
||||||
|
if ((octet1 == '\0') || ((octet1 >> 6) != 2))
|
||||||
|
{ *processed = 2; return 0; }
|
||||||
|
octet2 = text[2];
|
||||||
|
if ((octet2 == '\0') || ((octet2 >> 6) != 2))
|
||||||
|
{ *processed = 3; return 0; }
|
||||||
|
if ((octet3 == '\0') || ((octet3 >> 6) != 2))
|
||||||
|
{ *processed = 4; return 0; }
|
||||||
|
if (((octet == 0xf0) && !((octet1 >= 0x90) && (octet1 <= 0xbf))) ||
|
||||||
|
((octet == 0xf4) && !((octet1 >= 0x80) && (octet1 <= 0x8f))))
|
||||||
|
{ *processed = 2; return 0; }
|
||||||
|
if (octet >= 0xf0)
|
||||||
|
{
|
||||||
|
code = (((octet & 0x7) << 18) |
|
||||||
|
((octet1 & 0x3f) << 12) |
|
||||||
|
((octet2 & 0x3f) << 6) |
|
||||||
|
(octet3 & 0x3f));
|
||||||
|
*processed = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From: https://gist.github.com/MightyPork/52eda3e5677b4b03524e40c9f0ab1da5
|
||||||
|
__attribute__((annotate("oclint:suppress[high ncss method]")))
|
||||||
|
int set_codepoint(char *buf, int codepoint)
|
||||||
|
{
|
||||||
|
if (codepoint <= 0x7F)
|
||||||
|
{
|
||||||
|
*buf++ = (char)codepoint;
|
||||||
|
*buf++ = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0x07FF)
|
||||||
|
{
|
||||||
|
*buf++ = (char)(((codepoint >> 6) & 0x1F) | 0xC0);
|
||||||
|
*buf++ = (char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||||
|
*buf++ = '\0';
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0xFFFF)
|
||||||
|
{
|
||||||
|
*buf++ = (char)(((codepoint >> 12) & 0x0F) | 0xE0);
|
||||||
|
*buf++ = (char)(((codepoint >> 6) & 0x3F) | 0x80);
|
||||||
|
*buf++ = (char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||||
|
*buf++ = '\0';
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
else if (codepoint <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
*buf++ = (char)(((codepoint >> 18) & 0x07) | 0xF0);
|
||||||
|
*buf++ = (char)(((codepoint >> 12) & 0x3F) | 0x80);
|
||||||
|
*buf++ = (char)(((codepoint >> 6) & 0x3F) | 0x80);
|
||||||
|
*buf++ = (char)(((codepoint >> 0) & 0x3F) | 0x80);
|
||||||
|
*buf++ = '\0';
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
*buf++ = '\xEF';
|
||||||
|
*buf++ = '\xBF';
|
||||||
|
*buf++ = '\xBD';
|
||||||
|
*buf++ = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n_codepoints(char *text)
|
||||||
|
{
|
||||||
|
int proc = 0, length = 0;
|
||||||
|
while (*text != '\0')
|
||||||
|
{
|
||||||
|
if (get_codepoint(text, &proc) == 0)
|
||||||
|
break;
|
||||||
|
length++;
|
||||||
|
text += proc;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,12 @@ extern bool b_logging;
|
||||||
void _log(const char *fmt, ...);
|
void _log(const char *fmt, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void c_fatal(int code, const char *reason);
|
void c_fatal(int code, const char *reason, ...);
|
||||||
void m_prepare_dither(asc_state_t *state);
|
void m_prepare_dither(asc_state_t *state);
|
||||||
palette_t *get_palette_by_id(asc_style_t stl);
|
palette_t *get_palette_by_id(asc_style_t stl);
|
||||||
|
|
||||||
|
int get_codepoint(char *text, int *processed);
|
||||||
|
int set_codepoint(char *buf, int codepoint);
|
||||||
|
int n_codepoints(char *text);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define S_JSON_LSTA " [\n"
|
#define S_JSON_LSTA " [\n"
|
||||||
#define S_JSON_PBBW " { \"char\": \"%s\", \"fg\": 16777215, \"bg\": 0 }"
|
#define S_JSON_PBBW " { \"char\": \"%s\", \"fg\": 16777215, \"bg\": 0 }"
|
||||||
#define S_JSON_PRGB " { \"char\": \"\\u%04x\", \"fg\": %d, \"bg\": %d }"
|
#define S_JSON_PRGB " { \"char\": \"\\u%04x\", \"fg\": %d, \"bg\": %d }"
|
||||||
|
#define S_JSON_PUCC " { \"char\": \"\\u%04x\", \"fg\": %d, \"bg\": 0 }"
|
||||||
#define S_JSON_PBLK " { \"char\": \"%s\", \"fg\": %d, \"bg\": %d }"
|
#define S_JSON_PBLK " { \"char\": \"%s\", \"fg\": %d, \"bg\": %d }"
|
||||||
#define S_JSON_LEND " ],\n"
|
#define S_JSON_LEND " ],\n"
|
||||||
#define S_JSON_LEND_FINAL " ]\n"
|
#define S_JSON_LEND_FINAL " ]\n"
|
||||||
|
@ -33,13 +34,18 @@
|
||||||
"background: rgb(%d, %d, %d);\">&#%d;</td>"
|
"background: rgb(%d, %d, %d);\">&#%d;</td>"
|
||||||
#define S_HTML_PBLK "<td style=\"color: rgb(%d, %d, %d); "\
|
#define S_HTML_PBLK "<td style=\"color: rgb(%d, %d, %d); "\
|
||||||
"background: rgb(%d, %d, %d);\">%s</td>"
|
"background: rgb(%d, %d, %d);\">%s</td>"
|
||||||
|
#define S_HTML_PUCC "<td style=\"color: rgb(%d, %d, %d);\">&#%d;</td>"
|
||||||
|
#define S_HTML_PUBW "<td>&#%d;</td>"
|
||||||
#define S_HTML_PBBW "<td>%s</td>"
|
#define S_HTML_PBBW "<td>%s</td>"
|
||||||
#define S_HTML_LEND "</tr>\n"
|
#define S_HTML_LEND "</tr>\n"
|
||||||
#define S_HTML_TAIL "</table>"
|
#define S_HTML_TAIL "</table>"
|
||||||
|
|
||||||
#define S_ANSI "\033[%d;%dm"
|
#define S_ANSI "\033[%d;%dm"
|
||||||
#define S_ANSI_RGB "\033[38;2;%d;%d;%d;48;2;%d;%d;%dm"
|
#define S_ANSI_FG "\033[%dm"
|
||||||
#define S_ANSI_256 "\033[38;5;%d;48;5;%dm"
|
#define S_ANSI_RGB "\033[38;2;%d;%d;%d;48;2;%d;%d;%dm"
|
||||||
#define S_ANSI_RST "\033[0m"
|
#define S_ANSI_256 "\033[38;5;%d;48;5;%dm"
|
||||||
|
#define S_ANSI_FG_256 "\033[38;5;%dm"
|
||||||
|
#define S_ANSI_FG_RGB "\033[38;2;%d;%d;%dm"
|
||||||
|
#define S_ANSI_RST "\033[0m"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
13
src/main.c
13
src/main.c
|
@ -20,10 +20,9 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
#include "mod_blocks.h"
|
|
||||||
#include "mod_braille.h"
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
|
|
||||||
|
__attribute__((annotate("oclint:suppress[high npath complexity]")))
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
asc_args_t args;
|
asc_args_t args;
|
||||||
|
@ -40,10 +39,14 @@ int main(int argc, char **argv)
|
||||||
if (handler.prepare == NULL)
|
if (handler.prepare == NULL)
|
||||||
c_fatal(12, "this mode is not implemented yet");
|
c_fatal(12, "this mode is not implemented yet");
|
||||||
|
|
||||||
handler.prepare(&state);
|
if (!handler.prepare(&state))
|
||||||
handler.main(state);
|
c_fatal(15, "handler.prepare() said a big no-no");
|
||||||
|
|
||||||
|
if (!handler.main(state))
|
||||||
|
c_fatal(16, "handler.main() said a big no-no");
|
||||||
|
|
||||||
image_unload(state.image);
|
if (state.image != state.source_image)
|
||||||
|
image_unload(state.image);
|
||||||
image_unload(state.source_image);
|
image_unload(state.source_image);
|
||||||
|
|
||||||
if (args.out_style == ASC_STL_PALETTE)
|
if (args.out_style == ASC_STL_PALETTE)
|
||||||
|
|
|
@ -19,7 +19,7 @@ void __blk_end_line(asc_state_t s, bool final);
|
||||||
void __blk_end_output(asc_state_t s);
|
void __blk_end_output(asc_state_t s);
|
||||||
|
|
||||||
|
|
||||||
void mod_blocks_prepare(asc_state_t *state)
|
bool mod_blocks_prepare(asc_state_t *state)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
get_size_keep_aspect(
|
get_size_keep_aspect(
|
||||||
|
@ -33,9 +33,10 @@ void mod_blocks_prepare(asc_state_t *state)
|
||||||
state->image = image_resize(state->source_image, width, height);
|
state->image = image_resize(state->source_image, width, height);
|
||||||
if (state->args.dither)
|
if (state->args.dither)
|
||||||
m_prepare_dither(state);
|
m_prepare_dither(state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_blocks_main(asc_state_t state)
|
bool mod_blocks_main(asc_state_t state)
|
||||||
{
|
{
|
||||||
image_t *img = state.image;
|
image_t *img = state.image;
|
||||||
__blk_start_output(state);
|
__blk_start_output(state);
|
||||||
|
@ -52,6 +53,7 @@ void mod_blocks_main(asc_state_t state)
|
||||||
__blk_end_line(state, final);
|
__blk_end_line(state, final);
|
||||||
}
|
}
|
||||||
__blk_end_output(state);
|
__blk_end_output(state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __blk_start_output(asc_state_t state)
|
void __blk_start_output(asc_state_t state)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
|
|
||||||
void mod_blocks_prepare(asc_state_t *state);
|
bool mod_blocks_prepare(asc_state_t *state);
|
||||||
void mod_blocks_main(asc_state_t state);
|
bool mod_blocks_main(asc_state_t state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,7 +30,7 @@ void __bra_update2x4(image_t *img, rgba8 block[8], int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mod_braille_prepare(asc_state_t *state)
|
bool mod_braille_prepare(asc_state_t *state)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
get_size_keep_aspect(
|
get_size_keep_aspect(
|
||||||
|
@ -44,9 +44,10 @@ void mod_braille_prepare(asc_state_t *state)
|
||||||
state->image = image_resize(state->source_image, width, height);
|
state->image = image_resize(state->source_image, width, height);
|
||||||
if (state->args.dither)
|
if (state->args.dither)
|
||||||
m_prepare_dither(state);
|
m_prepare_dither(state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mod_braille_main(asc_state_t state)
|
bool mod_braille_main(asc_state_t state)
|
||||||
{
|
{
|
||||||
image_t *img = state.image;
|
image_t *img = state.image;
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@ void mod_braille_main(asc_state_t state)
|
||||||
__bra_end_line(state, final);
|
__bra_end_line(state, final);
|
||||||
}
|
}
|
||||||
__bra_end_output(state);
|
__bra_end_output(state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __bra_best_match_i(rgba8 a, rgba8 b, rgba8 t)
|
int __bra_best_match_i(rgba8 a, rgba8 b, rgba8 t)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
|
|
||||||
void mod_braille_prepare(asc_state_t *state);
|
bool mod_braille_prepare(asc_state_t *state);
|
||||||
void mod_braille_main(asc_state_t state);
|
bool mod_braille_main(asc_state_t state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "mod_charmap.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "colors.h"
|
||||||
|
#include "commons.h"
|
||||||
|
#include "fmt_strings.h"
|
||||||
|
|
||||||
|
void __chr_start_output(asc_state_t s);
|
||||||
|
void __chr_start_line(asc_state_t s, bool final);
|
||||||
|
void __chr_put_pixel(asc_state_t s, rgba8 fg, bool final);
|
||||||
|
void __chr_putc_bw(asc_state_t s, int cc, bool final);
|
||||||
|
void __chr_putc_ansi(asc_state_t s, int fg, int cc, bool final);
|
||||||
|
void __chr_putc_256(asc_state_t s, int fg, int cc, bool final);
|
||||||
|
void __chr_putc_true(asc_state_t s, rgba8 fg, int cc, bool final);
|
||||||
|
void __chr_end_line(asc_state_t s, bool final);
|
||||||
|
void __chr_end_output(asc_state_t s);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int n_codepoints;
|
||||||
|
int *codepoints;
|
||||||
|
} __m_cmap_userdata_t;
|
||||||
|
|
||||||
|
bool mod_cmap_prepare(asc_state_t *state)
|
||||||
|
{
|
||||||
|
static __m_cmap_userdata_t userdata;
|
||||||
|
static int codepoints[M_CMAP_MAX_CODEPOINTS];
|
||||||
|
userdata.codepoints = codepoints;
|
||||||
|
int n_cp = 0, cp, proc;
|
||||||
|
char *charset = state->args.charset;
|
||||||
|
while ((cp = get_codepoint(charset, &proc)) != 0)
|
||||||
|
{ codepoints[n_cp++] = cp; charset += proc; }
|
||||||
|
if (n_cp > M_CMAP_MAX_CODEPOINTS)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: maximum of %d codepoints is allowed, got %d\n",
|
||||||
|
M_CMAP_MAX_CODEPOINTS, n_cp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
userdata.n_codepoints = n_cp;
|
||||||
|
state->userdata = (void *)&userdata;
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
get_size_keep_aspect(
|
||||||
|
state->source_image->width * 2, state->source_image->height,
|
||||||
|
state->args.width, state->args.height, &width, &height);
|
||||||
|
LOG("Source size: %dx%d", state->source_image->width,
|
||||||
|
state->source_image->height);
|
||||||
|
LOG("Requested size: %dx%d", state->args.width, state->args.height);
|
||||||
|
LOG("Resizing image to %dx%d", width, height);
|
||||||
|
state->image = image_resize(state->source_image, width, height);
|
||||||
|
if (state->args.dither)
|
||||||
|
m_prepare_dither(state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mod_cmap_main(asc_state_t state)
|
||||||
|
{
|
||||||
|
image_t *img = state.image;
|
||||||
|
__chr_start_output(state);
|
||||||
|
for (int y = 0; y < img->height; y++)
|
||||||
|
{
|
||||||
|
bool final = y >= img->height;
|
||||||
|
__chr_start_line(state, final);
|
||||||
|
for (int x = 0; x < img->width; x++)
|
||||||
|
{
|
||||||
|
__chr_put_pixel(state, img->pixels[x + y * img->width], x >= img->width);
|
||||||
|
}
|
||||||
|
__chr_end_line(state, final);
|
||||||
|
}
|
||||||
|
__chr_end_output(state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_start_output(asc_state_t state)
|
||||||
|
{
|
||||||
|
if (state.args.out_format == ASC_FMT_JSON)
|
||||||
|
fprintf(state.out_file, S_JSON_HEAD,
|
||||||
|
state.image->width, state.image->height / 2);
|
||||||
|
else if (state.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(state.out_file, S_HTML_HEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_start_line(asc_state_t state, bool final)
|
||||||
|
{
|
||||||
|
(void)final;
|
||||||
|
if (state.args.out_format == ASC_FMT_JSON)
|
||||||
|
fprintf(state.out_file, S_JSON_LSTA);
|
||||||
|
else if (state.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(state.out_file, S_HTML_LSTA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_put_pixel(asc_state_t s, rgba8 fg, bool final)
|
||||||
|
{
|
||||||
|
float brightness = calc_brightness(fg);
|
||||||
|
__m_cmap_userdata_t data = *(__m_cmap_userdata_t *)s.userdata;
|
||||||
|
int ndx = floorf(brightness * data.n_codepoints);
|
||||||
|
if (ndx >= data.n_codepoints) ndx = data.n_codepoints - 1;
|
||||||
|
int codepoint = data.codepoints[ndx];
|
||||||
|
switch (s.args.out_style)
|
||||||
|
{
|
||||||
|
case ASC_STL_BLACKWHITE:
|
||||||
|
__chr_putc_bw(s, codepoint, final);
|
||||||
|
break;
|
||||||
|
case ASC_STL_ANSI_VGA:
|
||||||
|
case ASC_STL_ANSI_XTERM:
|
||||||
|
case ASC_STL_ANSI_DISCORD:
|
||||||
|
__chr_putc_ansi(s, closest_color(*s.palette, fg), codepoint, final);
|
||||||
|
break;
|
||||||
|
case ASC_STL_256COLOR:
|
||||||
|
__chr_putc_256(s, closest_color(c_palette_256, fg), codepoint, final);
|
||||||
|
break;
|
||||||
|
case ASC_STL_PALETTE:
|
||||||
|
__chr_putc_true(s, clamp_to_pal(*s.palette, fg), codepoint, final);
|
||||||
|
break;
|
||||||
|
case ASC_STL_TRUECOLOR:
|
||||||
|
__chr_putc_true(s, fg, codepoint, final);
|
||||||
|
break;
|
||||||
|
case ASC_STL_ENDL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_putc_bw(asc_state_t s, int cc, bool final)
|
||||||
|
{
|
||||||
|
static char buf[8];
|
||||||
|
set_codepoint(buf, cc);
|
||||||
|
if (s.args.out_format == ASC_FMT_JSON)
|
||||||
|
{
|
||||||
|
fprintf(s.out_file, S_JSON_PUCC, cc, 0xFFFFFF);
|
||||||
|
if (!final) fprintf(s.out_file, ",");
|
||||||
|
fprintf(s.out_file, "\n");
|
||||||
|
}
|
||||||
|
else if (s.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(s.out_file, S_HTML_PUBW, cc);
|
||||||
|
else
|
||||||
|
fprintf(s.out_file, "%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_putc_ansi(asc_state_t s, int fg, int cc, bool final)
|
||||||
|
{
|
||||||
|
static char buf[8];
|
||||||
|
rgba8 fgc = s.palette->palette[fg];
|
||||||
|
set_codepoint(buf, cc);
|
||||||
|
if (s.args.out_format == ASC_FMT_JSON)
|
||||||
|
{
|
||||||
|
fprintf(s.out_file, S_JSON_PUCC, cc, RGBN(fgc));
|
||||||
|
if (!final) fprintf(s.out_file, ",");
|
||||||
|
fprintf(s.out_file, "\n");
|
||||||
|
}
|
||||||
|
else if (s.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(s.out_file, S_HTML_PUCC, fgc.r, fgc.g, fgc.b, cc);
|
||||||
|
else
|
||||||
|
fprintf(s.out_file, S_ANSI_FG"%s", fg + (fg >= 8 ? 82 : 30), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_putc_256(asc_state_t s, int fg, int cc, bool final)
|
||||||
|
{
|
||||||
|
static char buf[8];
|
||||||
|
rgba8 fgc = pal256_to_rgb(*s.palette, fg);
|
||||||
|
set_codepoint(buf, cc);
|
||||||
|
if (s.args.out_format == ASC_FMT_JSON)
|
||||||
|
{
|
||||||
|
fprintf(s.out_file, S_JSON_PUCC, cc, RGBN(fgc));
|
||||||
|
if (!final) fprintf(s.out_file, ",");
|
||||||
|
fprintf(s.out_file, "\n");
|
||||||
|
}
|
||||||
|
else if (s.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(s.out_file, S_HTML_PUCC, fgc.r, fgc.g, fgc.b, cc);
|
||||||
|
else
|
||||||
|
fprintf(s.out_file, S_ANSI_FG_256"%s", fg, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_putc_true(asc_state_t s, rgba8 fg, int cc, bool final)
|
||||||
|
{
|
||||||
|
static char buf[8];
|
||||||
|
set_codepoint(buf, cc);
|
||||||
|
if (s.args.out_format == ASC_FMT_JSON)
|
||||||
|
{
|
||||||
|
fprintf(s.out_file, S_JSON_PUCC, cc, RGBN(fg));
|
||||||
|
if (!final) fprintf(s.out_file, ",");
|
||||||
|
fprintf(s.out_file, "\n");
|
||||||
|
}
|
||||||
|
else if (s.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(s.out_file, S_HTML_PUCC, fg.r, fg.g, fg.b, cc);
|
||||||
|
else
|
||||||
|
fprintf(s.out_file, S_ANSI_FG_RGB"%s", fg.r, fg.g, fg.b, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_end_line(asc_state_t state, bool final)
|
||||||
|
{
|
||||||
|
if (state.args.out_format == ASC_FMT_JSON)
|
||||||
|
fprintf(state.out_file, final ? S_JSON_LEND_FINAL : S_JSON_LEND);
|
||||||
|
else if (state.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(state.out_file, S_HTML_LEND);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (state.args.out_style != ASC_STL_BLACKWHITE)
|
||||||
|
fprintf(state.out_file, S_ANSI_RST);
|
||||||
|
fprintf(state.out_file, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __chr_end_output(asc_state_t state)
|
||||||
|
{
|
||||||
|
if (state.args.out_format == ASC_FMT_JSON)
|
||||||
|
fprintf(state.out_file, S_JSON_TAIL);
|
||||||
|
else if (state.args.out_format == ASC_FMT_HTML)
|
||||||
|
fprintf(state.out_file, S_HTML_TAIL);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* yaitaa - yet another image to ascii art converter
|
||||||
|
* Copyright (C) 2022 hatkidchan <hatkidchan at gmail dot 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/>.
|
||||||
|
*/
|
||||||
|
#ifndef _MOD_CHARMAP_
|
||||||
|
#define _MOD_CHARMAP_
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "colors.h"
|
||||||
|
#include "args.h"
|
||||||
|
|
||||||
|
#define M_CMAP_MAX_CODEPOINTS 256
|
||||||
|
|
||||||
|
bool mod_cmap_prepare(asc_state_t *state);
|
||||||
|
bool mod_cmap_main(asc_state_t state);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue