256-colors palette is now pre-computed on start
That kinda fixes weird issue with vertical stripes
This commit is contained in:
parent
7673f7e239
commit
ee81a72e56
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@ CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99 -ggdb
|
|||
CLIBS := -lm
|
||||
INCLUDES := -Isrc
|
||||
OBJECTS := obj/stb_image.o obj/stb_image_resize.o \
|
||||
obj/colors.o obj/args.o obj/image.o \
|
||||
obj/colors.o obj/args.o obj/image.o obj/commons.o \
|
||||
obj/mod_blocks.o
|
||||
|
||||
all: lib asciify
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "args.h"
|
||||
#include "colors.h"
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -242,6 +243,9 @@ int prepare_state(int argc, char **argv, asc_args_t args, asc_state_t *state)
|
|||
fclose(fp);
|
||||
}
|
||||
|
||||
if (args.out_style == ASC_STL_256COLOR)
|
||||
make_pal256(&c_palette_256, c_palette_ansi_vga);
|
||||
|
||||
state->out_file = stdout;
|
||||
if (strcmp(args.output_filename, "-"))
|
||||
state->out_file = fopen(args.output_filename, "wb");
|
||||
|
|
38
src/colors.c
38
src/colors.c
|
@ -11,6 +11,10 @@ palette_t c_palette_bw = {
|
|||
}
|
||||
};
|
||||
|
||||
palette_t c_palette_256 = {
|
||||
.n_colors = 0
|
||||
};
|
||||
|
||||
palette_t c_palette_ansi_discord = {
|
||||
.n_colors = 8,
|
||||
.palette = {
|
||||
|
@ -89,30 +93,11 @@ int closest_color(palette_t pal, rgba8 color)
|
|||
return nearest;
|
||||
}
|
||||
|
||||
int closest_256(palette_t pal, rgba8 color)
|
||||
{
|
||||
(void)pal;
|
||||
if (color.r == color.g && color.g == color.b)
|
||||
{
|
||||
if (color.r < 8) return 16;
|
||||
if (color.r > 248) return 231;
|
||||
return 232 + (int)ceil((color.r - 8.0) / 247.0 * 24.0);
|
||||
}
|
||||
int oc = 16;
|
||||
oc += 36 * (int)ceil(color.r / 255.0 * 5.0);
|
||||
oc += 6 * (int)ceil(color.g / 255.0 * 5.0);
|
||||
oc += (int)ceil(color.b / 255.0 * 5.0);
|
||||
return oc;
|
||||
}
|
||||
|
||||
rgba8 pal256_to_rgb(palette_t pal, int ndx)
|
||||
{
|
||||
(void)pal;
|
||||
rgba8 out = { 0, 0, 0, 255 };
|
||||
if (ndx < 16)
|
||||
{
|
||||
return pal.palette[ndx];
|
||||
}
|
||||
else if (ndx >= 232)
|
||||
if (ndx >= 232)
|
||||
{
|
||||
int l = (ndx - 232) * 255 / 24;
|
||||
out.r = out.g = out.b = l;
|
||||
|
@ -129,6 +114,17 @@ rgba8 pal256_to_rgb(palette_t pal, int ndx)
|
|||
return out;
|
||||
}
|
||||
|
||||
void make_pal256(palette_t *dst, palette_t ansi)
|
||||
{
|
||||
if (dst->n_colors == 256) return;
|
||||
dst->n_colors = 256;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
rgba8 res = pal256_to_rgb(ansi, i);
|
||||
memcpy(&dst->palette[i], &res, sizeof(rgba8));
|
||||
}
|
||||
}
|
||||
|
||||
float calc_brightness(rgba8 c)
|
||||
{
|
||||
return 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b;
|
||||
|
|
|
@ -14,13 +14,14 @@ typedef struct {
|
|||
} palette_t;
|
||||
|
||||
extern palette_t c_palette_bw;
|
||||
extern palette_t c_palette_256;
|
||||
extern palette_t c_palette_ansi_discord;
|
||||
extern palette_t c_palette_ansi_vga;
|
||||
extern palette_t c_palette_ansi_xterm;
|
||||
|
||||
int closest_color(palette_t pal, rgba8 color);
|
||||
int closest_256(palette_t pal, rgba8 color);
|
||||
rgba8 pal256_to_rgb(palette_t pal, int ndx);
|
||||
void make_pal256(palette_t *dst, palette_t ansi);
|
||||
bool load_palette_gpl(palette_t *pal, FILE *fp);
|
||||
bool load_palette_raw(palette_t *pal, FILE *fp);
|
||||
bool load_palette(palette_t *pal, FILE *fp);
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#include "colors.h"
|
||||
#include "commons.h"
|
||||
|
||||
void m_prepare_dither(asc_state_t *state)
|
||||
{
|
||||
if (state->args.dither)
|
||||
{
|
||||
image_t *res = NULL;
|
||||
switch (state->args.out_style)
|
||||
{
|
||||
case ASC_STL_BLACKWHITE:
|
||||
res = image_dither(state->image, c_palette_bw);
|
||||
break;
|
||||
case ASC_STL_ANSI_VGA:
|
||||
res = image_dither(state->image, c_palette_ansi_vga);
|
||||
break;
|
||||
case ASC_STL_ANSI_XTERM:
|
||||
res = image_dither(state->image, c_palette_ansi_xterm);
|
||||
break;
|
||||
case ASC_STL_ANSI_DISCORD:
|
||||
res = image_dither(state->image, c_palette_ansi_discord);
|
||||
break;
|
||||
case ASC_STL_256COLOR:
|
||||
res = image_dither(state->image, c_palette_256);
|
||||
break;
|
||||
case ASC_STL_PALETTE:
|
||||
res = image_dither(state->image, *state->palette);
|
||||
break;
|
||||
case ASC_STL_TRUECOLOR:
|
||||
case ASC_STL_ENDL:
|
||||
break;
|
||||
}
|
||||
if (res != NULL)
|
||||
{
|
||||
image_unload(state->image);
|
||||
state->image = res;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _COMMONS_H_
|
||||
#define _COMMONS_H_
|
||||
|
||||
#include "args.h"
|
||||
|
||||
void m_prepare_dither(asc_state_t *state);
|
||||
|
||||
#endif
|
|
@ -12,7 +12,6 @@ typedef struct {
|
|||
|
||||
typedef rgba8 (*dither_quantizer_t)(rgba8 clr, void *param);
|
||||
|
||||
|
||||
image_t *image_load(FILE *file);
|
||||
image_t *image_resize(image_t *img, int width, int height);
|
||||
image_t *image_dither(image_t *img, palette_t palette);
|
||||
|
|
|
@ -2,18 +2,12 @@
|
|||
#include "mod_blocks.h"
|
||||
#include "image.h"
|
||||
#include "colors.h"
|
||||
#include "commons.h"
|
||||
|
||||
const char *BLOCKS[4] = { " ", "\xe2\x96\x80", "\xe2\x96\x84", "\xe2\x96\x88" };
|
||||
const char *BLOCKS_ESC[4] = { " ", "\\u2580", "\\u2584", "\\u2588" };
|
||||
|
||||
|
||||
rgba8 __to_256(rgba8 c, void *p)
|
||||
{
|
||||
(void)p;
|
||||
return pal256_to_rgb(c_palette_ansi_vga, closest_256(c_palette_ansi_vga, c));
|
||||
}
|
||||
|
||||
|
||||
void mod_blocks_prepare(asc_state_t *state)
|
||||
{
|
||||
int w, h;
|
||||
|
@ -21,49 +15,8 @@ void mod_blocks_prepare(asc_state_t *state)
|
|||
state->source_image->width, state->source_image->height,
|
||||
state->args.width, state->args.height * 2, &w, &h);
|
||||
h = (h / 2) * 2;
|
||||
if (state->args.verbose)
|
||||
{
|
||||
fprintf(stderr, "src: %dx%d\n",
|
||||
state->source_image->width,
|
||||
state->source_image->height);
|
||||
fprintf(stderr, "tgt: %dx%d\n", state->args.width, state->args.height * 2);
|
||||
fprintf(stderr, "dst: %dx%d\n", w, h);
|
||||
}
|
||||
state->image = image_resize(state->source_image, w, h);
|
||||
// TODO: dither
|
||||
if (state->args.dither)
|
||||
{
|
||||
image_t *res = NULL;
|
||||
switch (state->args.out_style)
|
||||
{
|
||||
case ASC_STL_BLACKWHITE:
|
||||
res = image_dither(state->image, c_palette_bw);
|
||||
break;
|
||||
case ASC_STL_ANSI_VGA:
|
||||
res = image_dither(state->image, c_palette_ansi_vga);
|
||||
break;
|
||||
case ASC_STL_ANSI_XTERM:
|
||||
res = image_dither(state->image, c_palette_ansi_xterm);
|
||||
break;
|
||||
case ASC_STL_ANSI_DISCORD:
|
||||
res = image_dither(state->image, c_palette_ansi_discord);
|
||||
break;
|
||||
case ASC_STL_256COLOR:
|
||||
res = image_dither_fn(state->image, __to_256, NULL);
|
||||
break;
|
||||
case ASC_STL_PALETTE:
|
||||
res = image_dither(state->image, *state->palette);
|
||||
break;
|
||||
case ASC_STL_TRUECOLOR:
|
||||
case ASC_STL_ENDL:
|
||||
break;
|
||||
}
|
||||
if (res != NULL)
|
||||
{
|
||||
image_unload(state->image);
|
||||
state->image = res;
|
||||
}
|
||||
}
|
||||
m_prepare_dither(state);
|
||||
}
|
||||
|
||||
void __start_output(asc_state_t state)
|
||||
|
@ -254,8 +207,8 @@ void __put_pixel(asc_state_t state, rgba8 top, rgba8 bot, bool final)
|
|||
break;
|
||||
case ASC_STL_256COLOR:
|
||||
{
|
||||
int index_top = closest_256(c_palette_ansi_vga, top),
|
||||
index_bot = closest_256(c_palette_ansi_vga, bot);
|
||||
int index_top = closest_color(c_palette_256, top),
|
||||
index_bot = closest_color(c_palette_256, bot);
|
||||
__putc_256(fp, fmt, final, index_top, index_bot, c_palette_ansi_vga);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue