forked from hkc/cc-stuff
Moved stuff into separate functions, minor cleanup
This commit is contained in:
parent
a0450a7d59
commit
1eccdde3a3
264
img2cpi.c
264
img2cpi.c
|
@ -76,6 +76,8 @@ struct image {
|
|||
struct image_pal {
|
||||
int w, h;
|
||||
uint8_t *pixels;
|
||||
const union color *palette;
|
||||
size_t palette_size;
|
||||
};
|
||||
|
||||
bool parse_cmdline(int argc, char **argv);
|
||||
|
@ -89,6 +91,9 @@ float get_color_brightness(union color clr);
|
|||
void image_unload(struct image *img);
|
||||
void get_size_keep_aspect(int w, int h, int dw, int dh, int *ow, int *oh);
|
||||
|
||||
void convert_2x3(const struct image_pal *img, struct cc_char *characters);
|
||||
void convert_8x11(const struct image_pal *img, struct cc_char *characters);
|
||||
|
||||
const char *known_file_extensions[] = {
|
||||
".png", ".jpg", ".jpeg", ".jfif", ".jpg", ".gif",
|
||||
".tga", ".bmp", ".hdr", ".pnm", 0
|
||||
|
@ -190,7 +195,6 @@ int main(int argc, char **argv) {
|
|||
small_w * sizeof(union color));
|
||||
}
|
||||
|
||||
|
||||
// TODO: actually do stuff
|
||||
struct cc_char *characters = calloc(args.width * args.height, sizeof(struct cc_char));
|
||||
|
||||
|
@ -200,105 +204,10 @@ int main(int argc, char **argv) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
FILE *tmp = fopen("/tmp/img.raw", "wb");
|
||||
for (int i = 0; i < quantized_image->w * quantized_image->h; i++) {
|
||||
union color pix = palette[quantized_image->pixels[i]];
|
||||
fputc(pix.rgba.r, tmp);
|
||||
fputc(pix.rgba.g, tmp);
|
||||
fputc(pix.rgba.b, tmp);
|
||||
}
|
||||
fclose(tmp);
|
||||
|
||||
if (args.fast_mode) {
|
||||
// use old 2x3
|
||||
for (int y = 0; y < args.height; y++) {
|
||||
for (int x = 0; x < args.width; x++) {
|
||||
unsigned char darkest_i = 0, brightest_i = 0;
|
||||
float darkest_diff = 0xffffff, brightest_diff = 0;
|
||||
|
||||
for (int oy = 0; oy < 3; oy++) {
|
||||
for (int ox = 0; ox < 2; ox++) {
|
||||
unsigned char pix = quantized_image->pixels[ox + (x + (y * 3 + oy) * args.width) * 2];
|
||||
float brightness = get_color_brightness(palette[pix]);
|
||||
if (brightness >= brightest_diff) {
|
||||
brightest_i = pix;
|
||||
brightest_diff = brightness;
|
||||
}
|
||||
if (brightness <= darkest_diff) {
|
||||
darkest_i = pix;
|
||||
darkest_diff = brightness;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char bitmap = 0;
|
||||
const static unsigned char pixel_bits[3][2] = { { 1, 2}, { 4, 8 }, { 16, 0 } };
|
||||
for (int oy = 0; oy < 3; oy++) {
|
||||
for (int ox = 0; ox < 2; ox++) {
|
||||
if (ox == 1 && oy == 2) continue;
|
||||
unsigned char pix = quantized_image->pixels[ox + (x + (y * 3 + oy) * args.width) * 2];
|
||||
float diff_bg = get_color_difference(palette[darkest_i], palette[pix]);
|
||||
float diff_fg = get_color_difference(palette[brightest_i], palette[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap |= pixel_bits[oy][ox];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unsigned char pix = quantized_image->pixels[1 + (x + (y * 3 + 2) * args.width) * 2];
|
||||
float diff_bg = get_color_difference(palette[darkest_i], palette[pix]);
|
||||
float diff_fg = get_color_difference(palette[brightest_i], palette[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap ^= 31;
|
||||
unsigned char tmp = darkest_i;
|
||||
darkest_i = brightest_i;
|
||||
brightest_i = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
characters[x + y * args.width].character = 0x80 + bitmap;
|
||||
characters[x + y * args.width].bg = darkest_i;
|
||||
characters[x + y * args.width].fg = brightest_i;
|
||||
}
|
||||
}
|
||||
convert_2x3(quantized_image, characters);
|
||||
} else {
|
||||
// use new 8x11 character matching
|
||||
for (int y = 0; y < args.height; y++) {
|
||||
for (int x = 0; x < args.width; x++) {
|
||||
// Oh boy...
|
||||
float min_diff = 0xffffff;
|
||||
char closest_sym = 0x00, closest_color = 0xae;
|
||||
for (int sym = 0x01; sym <= 0xFF; sym++) {
|
||||
if (sym == '\t' || sym == '\n' || sym == '\r' || sym == '\x0e') {
|
||||
continue;
|
||||
}
|
||||
for (int color = 0x00; color <= 0xff; color++) {
|
||||
union color cell_bg = palette[color & 0xF],
|
||||
cell_fg = palette[color >> 4];
|
||||
float difference = 0;
|
||||
for (int oy = 0; oy < 11; oy++) {
|
||||
unsigned char sym_line = font_atlas[sym][oy];
|
||||
for (int ox = 0; ox < 8; ox++) {
|
||||
bool lit = sym_line & (0x80 >> ox);
|
||||
union color pixel = palette[quantized_image->pixels[
|
||||
ox + (x + (y * 11 + oy) * args.width) * 8
|
||||
]];
|
||||
difference += get_color_difference(pixel, lit ? cell_fg : cell_bg);
|
||||
}
|
||||
}
|
||||
if (difference <= min_diff) {
|
||||
min_diff = difference;
|
||||
closest_sym = sym;
|
||||
closest_color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
characters[x + y * args.width].character = closest_sym;
|
||||
characters[x + y * args.width].bg = closest_color & 0xF;
|
||||
characters[x + y * args.width].fg = closest_color >> 4;
|
||||
}
|
||||
}
|
||||
convert_8x11(quantized_image, characters);
|
||||
}
|
||||
|
||||
// TODO: implement something other than CPIv0
|
||||
|
@ -582,6 +491,8 @@ struct image_pal *image_quantize(struct image *original, const union color *colo
|
|||
out->w = original->w;
|
||||
out->h = original->h;
|
||||
out->pixels = calloc(original->w, original->h);
|
||||
out->palette = colors;
|
||||
out->palette_size = n_colors;
|
||||
|
||||
for (int i = 0; i < out->w * out->h; i++) {
|
||||
int closest_color = 0;
|
||||
|
@ -610,40 +521,133 @@ float get_color_brightness(union color clr) {
|
|||
return get_color_difference(clr, (union color){ .v = 0 });
|
||||
}
|
||||
|
||||
void convert_2x3(const struct image_pal *img, struct cc_char *characters) {
|
||||
int w = img->w / 2, h = img->h / 3;
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
unsigned char darkest_i = 0, brightest_i = 0;
|
||||
float darkest_diff = 0xffffff, brightest_diff = 0;
|
||||
|
||||
for (int oy = 0; oy < 3; oy++) {
|
||||
for (int ox = 0; ox < 2; ox++) {
|
||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
||||
float brightness = get_color_brightness(img->palette[pix]);
|
||||
if (brightness >= brightest_diff) {
|
||||
brightest_i = pix;
|
||||
brightest_diff = brightness;
|
||||
}
|
||||
if (brightness <= darkest_diff) {
|
||||
darkest_i = pix;
|
||||
darkest_diff = brightness;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char bitmap = 0;
|
||||
const static unsigned char pixel_bits[3][2] = { { 1, 2}, { 4, 8 }, { 16, 0 } };
|
||||
for (int oy = 0; oy < 3; oy++) {
|
||||
for (int ox = 0; ox < 2; ox++) {
|
||||
if (ox == 1 && oy == 2) continue;
|
||||
unsigned char pix = img->pixels[ox + (x + (y * 3 + oy) * w) * 2];
|
||||
float diff_bg = get_color_difference(img->palette[darkest_i], img->palette[pix]);
|
||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap |= pixel_bits[oy][ox];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
unsigned char pix = img->pixels[1 + (x + (y * 3 + 2) * w) * 2];
|
||||
float diff_bg = get_color_difference(img->palette[darkest_i], img->palette[pix]);
|
||||
float diff_fg = get_color_difference(img->palette[brightest_i], img->palette[pix]);
|
||||
if (diff_fg < diff_bg) {
|
||||
bitmap ^= 31;
|
||||
unsigned char tmp = darkest_i;
|
||||
darkest_i = brightest_i;
|
||||
brightest_i = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
characters[x + y * w].character = 0x80 + bitmap;
|
||||
characters[x + y * w].bg = darkest_i;
|
||||
characters[x + y * w].fg = brightest_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void convert_8x11(const struct image_pal *img, struct cc_char *characters) {
|
||||
int w = img->w / 8, h = img->h / 11;
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
float min_diff = 0xffffff;
|
||||
char closest_sym = 0x00, closest_color = 0xae;
|
||||
for (int sym = 0x01; sym <= 0xFF; sym++) {
|
||||
if (sym == '\t' || sym == '\n' || sym == '\r' || sym == '\x0e') {
|
||||
continue;
|
||||
}
|
||||
for (int color = 0x00; color <= 0xff; color++) {
|
||||
union color cell_bg = img->palette[color & 0xF],
|
||||
cell_fg = img->palette[color >> 4];
|
||||
float difference = 0;
|
||||
for (int oy = 0; oy < 11; oy++) {
|
||||
unsigned char sym_line = font_atlas[sym][oy];
|
||||
for (int ox = 0; ox < 8; ox++) {
|
||||
bool lit = sym_line & (0x80 >> ox);
|
||||
union color pixel = img->palette[img->pixels[
|
||||
ox + (x + (y * 11 + oy) * w) * 8
|
||||
]];
|
||||
difference += get_color_difference(pixel, lit ? cell_fg : cell_bg);
|
||||
}
|
||||
}
|
||||
if (difference <= min_diff) {
|
||||
min_diff = difference;
|
||||
closest_sym = sym;
|
||||
closest_color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
characters[x + y * w].character = closest_sym;
|
||||
characters[x + y * w].bg = closest_color & 0xF;
|
||||
characters[x + y * w].fg = closest_color >> 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const union color DEFAULT_PALETTE[16] = {
|
||||
{ 0xf0, 0xf0, 0xf0, 0xff },
|
||||
{ 0xf2, 0xb2, 0x33, 0xff },
|
||||
{ 0xe5, 0x7f, 0xd8, 0xff },
|
||||
{ 0x99, 0xb2, 0xf2, 0xff },
|
||||
{ 0xde, 0xde, 0x6c, 0xff },
|
||||
{ 0x7f, 0xcc, 0x19, 0xff },
|
||||
{ 0xf2, 0xb2, 0xcc, 0xff },
|
||||
{ 0x4c, 0x4c, 0x4c, 0xff },
|
||||
{ 0x99, 0x99, 0x99, 0xff },
|
||||
{ 0x4c, 0x99, 0xb2, 0xff },
|
||||
{ 0xb2, 0x66, 0xe5, 0xff },
|
||||
{ 0x33, 0x66, 0xcc, 0xff },
|
||||
{ 0x7f, 0x66, 0x4c, 0xff },
|
||||
{ 0x57, 0xa6, 0x4e, 0xff },
|
||||
{ 0xcc, 0x4c, 0x4c, 0xff },
|
||||
{ 0x11, 0x11, 0x11, 0xff }
|
||||
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||
{ { 0xf2, 0xb2, 0x33, 0xff } },
|
||||
{ { 0xe5, 0x7f, 0xd8, 0xff } },
|
||||
{ { 0x99, 0xb2, 0xf2, 0xff } },
|
||||
{ { 0xde, 0xde, 0x6c, 0xff } },
|
||||
{ { 0x7f, 0xcc, 0x19, 0xff } },
|
||||
{ { 0xf2, 0xb2, 0xcc, 0xff } },
|
||||
{ { 0x4c, 0x4c, 0x4c, 0xff } },
|
||||
{ { 0x99, 0x99, 0x99, 0xff } },
|
||||
{ { 0x4c, 0x99, 0xb2, 0xff } },
|
||||
{ { 0xb2, 0x66, 0xe5, 0xff } },
|
||||
{ { 0x33, 0x66, 0xcc, 0xff } },
|
||||
{ { 0x7f, 0x66, 0x4c, 0xff } },
|
||||
{ { 0x57, 0xa6, 0x4e, 0xff } },
|
||||
{ { 0xcc, 0x4c, 0x4c, 0xff } },
|
||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||
}, DEFAULT_GRAY_PALETTE[16] = {
|
||||
{ 0xf0, 0xf0, 0xf0, 0xff },
|
||||
{ 0x9d, 0x9d, 0x9d, 0xff },
|
||||
{ 0xbe, 0xbe, 0xbe, 0xff },
|
||||
{ 0xbf, 0xbf, 0xbf, 0xff },
|
||||
{ 0xb8, 0xb8, 0xb8, 0xff },
|
||||
{ 0x76, 0x76, 0x76, 0xff },
|
||||
{ 0xd0, 0xd0, 0xd0, 0xff },
|
||||
{ 0x4c, 0x4c, 0x4c, 0xff },
|
||||
{ 0x99, 0x99, 0x99, 0xff },
|
||||
{ 0x87, 0x87, 0x87, 0xff },
|
||||
{ 0xa9, 0xa9, 0xa9, 0xff },
|
||||
{ 0x77, 0x77, 0x77, 0xff },
|
||||
{ 0x65, 0x65, 0x65, 0xff },
|
||||
{ 0x6e, 0x6e, 0x6e, 0xff },
|
||||
{ 0x76, 0x76, 0x76, 0xff },
|
||||
{ 0x11, 0x11, 0x11, 0xff }
|
||||
{ { 0xf0, 0xf0, 0xf0, 0xff } },
|
||||
{ { 0x9d, 0x9d, 0x9d, 0xff } },
|
||||
{ { 0xbe, 0xbe, 0xbe, 0xff } },
|
||||
{ { 0xbf, 0xbf, 0xbf, 0xff } },
|
||||
{ { 0xb8, 0xb8, 0xb8, 0xff } },
|
||||
{ { 0x76, 0x76, 0x76, 0xff } },
|
||||
{ { 0xd0, 0xd0, 0xd0, 0xff } },
|
||||
{ { 0x4c, 0x4c, 0x4c, 0xff } },
|
||||
{ { 0x99, 0x99, 0x99, 0xff } },
|
||||
{ { 0x87, 0x87, 0x87, 0xff } },
|
||||
{ { 0xa9, 0xa9, 0xa9, 0xff } },
|
||||
{ { 0x77, 0x77, 0x77, 0xff } },
|
||||
{ { 0x65, 0x65, 0x65, 0xff } },
|
||||
{ { 0x6e, 0x6e, 0x6e, 0xff } },
|
||||
{ { 0x76, 0x76, 0x76, 0xff } },
|
||||
{ { 0x11, 0x11, 0x11, 0xff } }
|
||||
};
|
||||
|
||||
const char font_atlas[256][11] = {
|
||||
|
|
Loading…
Reference in New Issue