256-colors palette is now pre-computed on start

That kinda fixes weird issue with vertical stripes
This commit is contained in:
Casey 2022-02-03 14:19:39 +03:00
parent 7673f7e239
commit ee81a72e56
8 changed files with 75 additions and 75 deletions

View File

@ -2,7 +2,7 @@ CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99 -ggdb
CLIBS := -lm 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/colors.o obj/args.o obj/image.o obj/commons.o \
obj/mod_blocks.o obj/mod_blocks.o
all: lib asciify all: lib asciify

View File

@ -1,4 +1,5 @@
#include "args.h" #include "args.h"
#include "colors.h"
#include <getopt.h> #include <getopt.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.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); fclose(fp);
} }
if (args.out_style == ASC_STL_256COLOR)
make_pal256(&c_palette_256, c_palette_ansi_vga);
state->out_file = stdout; state->out_file = stdout;
if (strcmp(args.output_filename, "-")) if (strcmp(args.output_filename, "-"))
state->out_file = fopen(args.output_filename, "wb"); state->out_file = fopen(args.output_filename, "wb");

View File

@ -11,6 +11,10 @@ palette_t c_palette_bw = {
} }
}; };
palette_t c_palette_256 = {
.n_colors = 0
};
palette_t c_palette_ansi_discord = { palette_t c_palette_ansi_discord = {
.n_colors = 8, .n_colors = 8,
.palette = { .palette = {
@ -89,30 +93,11 @@ int closest_color(palette_t pal, rgba8 color)
return nearest; 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) rgba8 pal256_to_rgb(palette_t pal, int ndx)
{ {
(void)pal;
rgba8 out = { 0, 0, 0, 255 }; rgba8 out = { 0, 0, 0, 255 };
if (ndx < 16) if (ndx >= 232)
{
return pal.palette[ndx];
}
else if (ndx >= 232)
{ {
int l = (ndx - 232) * 255 / 24; int l = (ndx - 232) * 255 / 24;
out.r = out.g = out.b = l; out.r = out.g = out.b = l;
@ -129,6 +114,17 @@ rgba8 pal256_to_rgb(palette_t pal, int ndx)
return out; 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) 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;

View File

@ -14,13 +14,14 @@ typedef struct {
} palette_t; } palette_t;
extern palette_t c_palette_bw; 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_discord;
extern palette_t c_palette_ansi_vga; extern palette_t c_palette_ansi_vga;
extern palette_t c_palette_ansi_xterm; extern palette_t c_palette_ansi_xterm;
int closest_color(palette_t pal, rgba8 color); 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); 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_gpl(palette_t *pal, FILE *fp);
bool load_palette_raw(palette_t *pal, FILE *fp); bool load_palette_raw(palette_t *pal, FILE *fp);
bool load_palette(palette_t *pal, FILE *fp); bool load_palette(palette_t *pal, FILE *fp);

39
src/commons.c Normal file
View File

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

8
src/commons.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _COMMONS_H_
#define _COMMONS_H_
#include "args.h"
void m_prepare_dither(asc_state_t *state);
#endif

View File

@ -12,7 +12,6 @@ typedef struct {
typedef rgba8 (*dither_quantizer_t)(rgba8 clr, void *param); typedef rgba8 (*dither_quantizer_t)(rgba8 clr, void *param);
image_t *image_load(FILE *file); image_t *image_load(FILE *file);
image_t *image_resize(image_t *img, int width, int height); image_t *image_resize(image_t *img, int width, int height);
image_t *image_dither(image_t *img, palette_t palette); image_t *image_dither(image_t *img, palette_t palette);

View File

@ -2,18 +2,12 @@
#include "mod_blocks.h" #include "mod_blocks.h"
#include "image.h" #include "image.h"
#include "colors.h" #include "colors.h"
#include "commons.h"
const char *BLOCKS[4] = { " ", "\xe2\x96\x80", "\xe2\x96\x84", "\xe2\x96\x88" }; const char *BLOCKS[4] = { " ", "\xe2\x96\x80", "\xe2\x96\x84", "\xe2\x96\x88" };
const char *BLOCKS_ESC[4] = { " ", "\\u2580", "\\u2584", "\\u2588" }; 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) void mod_blocks_prepare(asc_state_t *state)
{ {
int w, h; int w, h;
@ -21,49 +15,8 @@ void mod_blocks_prepare(asc_state_t *state)
state->source_image->width, state->source_image->height, state->source_image->width, state->source_image->height,
state->args.width, state->args.height * 2, &w, &h); state->args.width, state->args.height * 2, &w, &h);
h = (h / 2) * 2; 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); state->image = image_resize(state->source_image, w, h);
// TODO: dither m_prepare_dither(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_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;
}
}
} }
void __start_output(asc_state_t 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; break;
case ASC_STL_256COLOR: case ASC_STL_256COLOR:
{ {
int index_top = closest_256(c_palette_ansi_vga, top), int index_top = closest_color(c_palette_256, top),
index_bot = closest_256(c_palette_ansi_vga, bot); index_bot = closest_color(c_palette_256, bot);
__putc_256(fp, fmt, final, index_top, index_bot, c_palette_ansi_vga); __putc_256(fp, fmt, final, index_top, index_bot, c_palette_ansi_vga);
} }
break; break;