Laid out basic project structure
This commit is contained in:
parent
f78f66cf9a
commit
18701f56a6
6
Makefile
6
Makefile
|
@ -1,7 +1,9 @@
|
||||||
CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99
|
CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99 -ggdb
|
||||||
CLIBS := -lm
|
CLIBS := -lm
|
||||||
INCLUDES := -Isrc
|
INCLUDES := -Isrc
|
||||||
OBJECTS := obj/stb_image.o
|
OBJECTS := obj/stb_image.o obj/stb_image_resize.o \
|
||||||
|
obj/colors.o obj/args.o obj/image.o \
|
||||||
|
obj/mod_blocks.o
|
||||||
|
|
||||||
all: lib asciify
|
all: lib asciify
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Why?
|
||||||
|
I just wasn't happy with state of old project, so I thought about recreating it.
|
||||||
|
|
||||||
|
# Anything new?
|
||||||
|
Nothing.
|
||||||
|
|
||||||
|
Oh wait. It's single binary now. Yay.
|
|
@ -0,0 +1,265 @@
|
||||||
|
#include "args.h"
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int value;
|
||||||
|
char *strings[8];
|
||||||
|
char *description;
|
||||||
|
} __option_t;
|
||||||
|
|
||||||
|
int __find_value(const __option_t *options, char *option);
|
||||||
|
void __print_options(const __option_t *options);
|
||||||
|
|
||||||
|
const __option_t __mode_options[ASC_MOD_ENDL + 1] = {
|
||||||
|
{ ASC_MOD_BLOCKS,
|
||||||
|
{ "b", "blk", "blocks", NULL },
|
||||||
|
"Box-drawing characters (\342\226\204) (default)" },
|
||||||
|
{ ASC_MOD_BRAILLE,
|
||||||
|
{ "r", "brl", "braille", NULL },
|
||||||
|
"Braille characters (literally stolen from MineOS)" },
|
||||||
|
{ ASC_MOD_GRADIENT,
|
||||||
|
{ "g", "grd", "gradient", NULL },
|
||||||
|
"Gradient of characters. No matching at all" },
|
||||||
|
{ ASC_MOD_BRUTEFORCE,
|
||||||
|
{ "f", "guess", "bruteforce", NULL },
|
||||||
|
"Looking for best possible character" },
|
||||||
|
{ -1, { NULL }, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const __option_t __style_options[ASC_STL_ENDL + 1] = {
|
||||||
|
{ ASC_STL_BLACKWHITE,
|
||||||
|
{ "1", "bw", "black-white", "1bit", NULL },
|
||||||
|
"1-bit black/white" },
|
||||||
|
{ ASC_STL_ANSI_VGA,
|
||||||
|
{ "vga", "ansi-vga", NULL },
|
||||||
|
"VGA palette" },
|
||||||
|
{ ASC_STL_ANSI_XTERM,
|
||||||
|
{ "xterm", "ansi-xterm", NULL },
|
||||||
|
"xTerm palette. A bit more rough, compared to VGA" },
|
||||||
|
{ ASC_STL_ANSI_DISCORD,
|
||||||
|
{ "discord", "ansi-discord", NULL },
|
||||||
|
"Palette in Discord ANSI highlight" },
|
||||||
|
{ ASC_STL_256COLOR,
|
||||||
|
{ "256", "pal256", "8bit", NULL },
|
||||||
|
"256-color palette (default)" },
|
||||||
|
{ ASC_STL_TRUECOLOR,
|
||||||
|
{ "true", "truecolor", "24bit", NULL },
|
||||||
|
"24-bit RGB (TrueColor)" },
|
||||||
|
{ ASC_STL_PALETTE,
|
||||||
|
{ "pal", "palette", "custom", NULL },
|
||||||
|
"Custom palette (specified via -P)" },
|
||||||
|
{ -1, { NULL }, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
const __option_t __format_options[ASC_FMT_ENDL + 1] = {
|
||||||
|
{ ASC_FMT_ANSI,
|
||||||
|
{ "ansi", "raw", NULL },
|
||||||
|
"Output, suitable for terminal (default)" },
|
||||||
|
{ ASC_FMT_HTML,
|
||||||
|
{ "html", NULL },
|
||||||
|
"Output as HTML table" },
|
||||||
|
{ ASC_FMT_JSON,
|
||||||
|
{ "json", NULL },
|
||||||
|
"Output as JSON 2D array of characters with properties" },
|
||||||
|
{ -1, { NULL }, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
void usage(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
fprintf(stderr, "usage: %s ", *argv);
|
||||||
|
fprintf(stderr, "[-vhd] [-O FILE] [-W WIDTH] [-H HEIGHT] ");
|
||||||
|
fprintf(stderr, "[-M MODE] [-S STYLE] [-F FORMAT] [-P PALETTE] ");
|
||||||
|
fprintf(stderr, "FILE\n\n");
|
||||||
|
fprintf(stderr, "-v\t\tEnable verbose mode\n");
|
||||||
|
fprintf(stderr, "-h\t\tShow this help\n");
|
||||||
|
fprintf(stderr, "-d\t\tEnable dithering\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "-O FILE\t\tOutput file. Default: - (stdout)\n");
|
||||||
|
fprintf(stderr, "-W WIDTH\tOutput width (in characters)\n");
|
||||||
|
fprintf(stderr, "-H HEIGHT\tOutput height (in characters)\n");
|
||||||
|
fprintf(stderr, "-M MODE\t\tOutput mode\n");
|
||||||
|
fprintf(stderr, "-S STYLE\tStyle (palette)\n");
|
||||||
|
fprintf(stderr, "-F FORMAT\tOutput format\n");
|
||||||
|
fprintf(stderr, "-P PALETTE\tPath to palette file (when -S pal)\n");
|
||||||
|
fprintf(stderr, "\n\n");
|
||||||
|
fprintf(stderr, "Options for MODE:\n");
|
||||||
|
__print_options(__mode_options);
|
||||||
|
fprintf(stderr, "Options for STYLE:\n");
|
||||||
|
__print_options(__style_options);
|
||||||
|
fprintf(stderr, "Options for FORMAT:\n");
|
||||||
|
__print_options(__format_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_args(int argc, char **argv, asc_args_t *args)
|
||||||
|
{
|
||||||
|
args->input_filename = NULL;
|
||||||
|
args->output_filename = "-";
|
||||||
|
args->palette_filename = NULL;
|
||||||
|
args->width = 80;
|
||||||
|
args->height = 24;
|
||||||
|
args->out_format = ASC_FMT_ANSI;
|
||||||
|
args->out_style = ASC_STL_256COLOR;
|
||||||
|
args->mode = ASC_MOD_BLOCKS;
|
||||||
|
args->dither = false;
|
||||||
|
args->verbose = false;
|
||||||
|
args->charset = " .'-*+$@";
|
||||||
|
int c;
|
||||||
|
while ((c = getopt(argc, argv, "vhdW:H:M:S:F:P:O:")) != -1)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'v':
|
||||||
|
args->verbose = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(argc, argv);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
args->dither = true;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
if ((args->width = atoi(optarg)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: WIDTH is invalid\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
if ((args->height = atoi(optarg)) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: HEIGHT is invalid\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
int val = __find_value(__mode_options, optarg);
|
||||||
|
if (val < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: invalid mode '%s'\n", optarg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args->mode = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
int val = __find_value(__style_options, optarg);
|
||||||
|
if (val < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: invalid style '%s'\n", optarg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args->out_style = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
{
|
||||||
|
int val = __find_value(__format_options, optarg);
|
||||||
|
if (val < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: invalid format '%s'\n", optarg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args->out_format = val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
args->palette_filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
args->output_filename = optarg;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
if (optopt == 'O'
|
||||||
|
|| optopt == 'W' || optopt == 'H'
|
||||||
|
|| optopt == 'S' || optopt == 'M' || optopt == 'F')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: missing argument for -%c\n", optopt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: Unknown parameter -%c\n", optopt);
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args->out_style == ASC_STL_PALETTE && args->palette_filename == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: no palette file provided, but palette mode selected\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (argc <= optind || argc < 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: no image provided\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
args->input_filename = argv[optind];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prepare_state(int argc, char **argv, asc_args_t args, asc_state_t *state)
|
||||||
|
{
|
||||||
|
(void)argc; (void)argv;
|
||||||
|
state->args = args;
|
||||||
|
|
||||||
|
FILE *image_file;
|
||||||
|
if ((image_file = fopen(args.input_filename, "rb")) == NULL
|
||||||
|
|| ferror(image_file) != 0)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
fprintf(stderr, "Error: failed to open file %s for reading: %d: %s\n",
|
||||||
|
args.input_filename, err, strerror(err));
|
||||||
|
return -100 - err;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->source_image = image_load(image_file);
|
||||||
|
fclose(image_file);
|
||||||
|
|
||||||
|
state->out_file = stdout;
|
||||||
|
if (strcmp(args.output_filename, "-"))
|
||||||
|
state->out_file = fopen(args.output_filename, "wb");
|
||||||
|
if (state->out_file == NULL)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
fprintf(stderr, "Error: failed to open file %s for writing: %d: %s\n",
|
||||||
|
args.output_filename, err, strerror(err));
|
||||||
|
return -100 - err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __find_value(const __option_t *options, char *option)
|
||||||
|
{
|
||||||
|
__option_t *opt;
|
||||||
|
while ((opt = (__option_t *)options++)->value >= 0)
|
||||||
|
{
|
||||||
|
char *str = opt->strings[0];
|
||||||
|
for (int i = 0; str != NULL; i++, str = opt->strings[i])
|
||||||
|
{
|
||||||
|
if (!strcmp(str, option)) return opt->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __print_options(const __option_t *options)
|
||||||
|
{
|
||||||
|
__option_t *opt;
|
||||||
|
while ((opt = (__option_t *)options++)->value >= 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, " - %s:\n\t", opt->description);
|
||||||
|
char *str = opt->strings[0];
|
||||||
|
for (int i = 0; str != NULL; i++, str = opt->strings[i])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s ", str);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef _ARGS_H_
|
||||||
|
#define _ARGS_H_
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASC_MOD_BLOCKS = 0,
|
||||||
|
ASC_MOD_BRAILLE = 1,
|
||||||
|
ASC_MOD_GRADIENT = 2,
|
||||||
|
ASC_MOD_BRUTEFORCE = 3,
|
||||||
|
ASC_MOD_ENDL = 4
|
||||||
|
} asc_mode_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASC_FMT_ANSI = 0,
|
||||||
|
ASC_FMT_HTML = 1,
|
||||||
|
ASC_FMT_JSON = 2,
|
||||||
|
ASC_FMT_ENDL = 3
|
||||||
|
} asc_format_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASC_STL_BLACKWHITE = 0,
|
||||||
|
ASC_STL_ANSI_VGA = 1,
|
||||||
|
ASC_STL_ANSI_XTERM = 2,
|
||||||
|
ASC_STL_ANSI_DISCORD = 3,
|
||||||
|
ASC_STL_256COLOR = 4,
|
||||||
|
ASC_STL_TRUECOLOR = 5,
|
||||||
|
ASC_STL_PALETTE = 6,
|
||||||
|
ASC_STL_ENDL = 7
|
||||||
|
} asc_style_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *input_filename;
|
||||||
|
char *output_filename;
|
||||||
|
char *palette_filename;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
asc_format_t out_format;
|
||||||
|
asc_style_t out_style;
|
||||||
|
asc_mode_t mode;
|
||||||
|
bool dither;
|
||||||
|
bool verbose;
|
||||||
|
char *charset;
|
||||||
|
} asc_args_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
asc_args_t args;
|
||||||
|
image_t *source_image;
|
||||||
|
image_t *image;
|
||||||
|
palette_t *palette;
|
||||||
|
FILE *out_file;
|
||||||
|
} asc_state_t;
|
||||||
|
|
||||||
|
void usage(int argc, char **argv);
|
||||||
|
int parse_args(int argc, char **argv, asc_args_t *args);
|
||||||
|
int prepare_state(int argc, char **argv, asc_args_t args, asc_state_t *state);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include "colors.h"
|
||||||
|
|
||||||
|
palette_t c_palette_ansi_discord = {
|
||||||
|
.n_colors = 8,
|
||||||
|
.palette = {
|
||||||
|
{ 0x4f, 0x54, 0x5c, 0 },
|
||||||
|
{ 0xd1, 0x31, 0x35, 0 },
|
||||||
|
{ 0x85, 0x99, 0x00, 0 },
|
||||||
|
{ 0xb5, 0x89, 0x00, 0 },
|
||||||
|
{ 0x26, 0x8b, 0xd2, 0 },
|
||||||
|
{ 0xd3, 0x36, 0x82, 0 },
|
||||||
|
{ 0xd3, 0x36, 0x82, 0 },
|
||||||
|
{ 0xff, 0xff, 0xff, 0 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
palette_t c_palette_ansi_vga = {
|
||||||
|
.n_colors = 16,
|
||||||
|
.palette = {
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
{ 170, 0, 0, 0 },
|
||||||
|
{ 0, 170, 0, 0 },
|
||||||
|
{ 170, 85, 0, 0 },
|
||||||
|
{ 0, 0, 170, 0 },
|
||||||
|
{ 170, 0, 170, 0 },
|
||||||
|
{ 0, 170, 170, 0 },
|
||||||
|
{ 170, 170, 170, 0 },
|
||||||
|
{ 85, 85, 85, 0 },
|
||||||
|
{ 255, 85, 85, 0 },
|
||||||
|
{ 85, 255, 85, 0 },
|
||||||
|
{ 255, 255, 85, 0 },
|
||||||
|
{ 85, 85, 255, 0 },
|
||||||
|
{ 255, 85, 255, 0 },
|
||||||
|
{ 85, 255, 255, 0 },
|
||||||
|
{ 255, 255, 255, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
palette_t c_palette_ansi_xterm = {
|
||||||
|
.n_colors = 16,
|
||||||
|
.palette = {
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
{ 205, 0, 0, 0 },
|
||||||
|
{ 0, 205, 0, 0 },
|
||||||
|
{ 205, 205, 0, 0 },
|
||||||
|
{ 0, 0, 238, 0 },
|
||||||
|
{ 205, 0, 205, 0 },
|
||||||
|
{ 0, 205, 205, 0 },
|
||||||
|
{ 229, 229, 229, 0 },
|
||||||
|
{ 127, 127, 127, 0 },
|
||||||
|
{ 255, 0, 0, 0 },
|
||||||
|
{ 0, 255, 0, 0 },
|
||||||
|
{ 255, 255, 0, 0 },
|
||||||
|
{ 0, 0, 252, 0 },
|
||||||
|
{ 255, 0, 255, 0 },
|
||||||
|
{ 0, 255, 255, 0 },
|
||||||
|
{ 255, 255, 255, 0 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int closest_color(palette_t *pal, rgba8 color)
|
||||||
|
{
|
||||||
|
int nearest = -1;
|
||||||
|
int32_t min_distance = 0x0fffffff;
|
||||||
|
for (int i = 0; i < pal->n_colors; i++)
|
||||||
|
{
|
||||||
|
rgba8 pal_color = pal->palette[i];
|
||||||
|
int16_t dr = pal_color.r - color.r;
|
||||||
|
int16_t dg = pal_color.g - color.g;
|
||||||
|
int16_t db = pal_color.b - color.b;
|
||||||
|
int32_t distance = dr * dr + dg * dg + db * db;
|
||||||
|
if (distance < min_distance)
|
||||||
|
{
|
||||||
|
min_distance = distance;
|
||||||
|
nearest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_palette_gpl(palette_t *pal, FILE *fp)
|
||||||
|
{
|
||||||
|
(void)pal; (void)fp;
|
||||||
|
// TODO: load GNU palette file
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_palette_raw(palette_t *pal, FILE *fp)
|
||||||
|
{
|
||||||
|
(void)pal; (void)fp;
|
||||||
|
// TODO: load raw palette file
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_palette(palette_t *pal, FILE *fp)
|
||||||
|
{
|
||||||
|
(void)pal; (void)fp;
|
||||||
|
// TODO: guess palette file type and load it
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef _COLORS_H_
|
||||||
|
#define _COLORS_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
} rgba8;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int n_colors;
|
||||||
|
rgba8 palette[255];
|
||||||
|
} palette_t;
|
||||||
|
|
||||||
|
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);
|
||||||
|
void load_palette_gpl(palette_t *pal, FILE *fp);
|
||||||
|
void load_palette_raw(palette_t *pal, FILE *fp);
|
||||||
|
void load_palette(palette_t *pal, FILE *fp);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "image.h"
|
||||||
|
#include "stb_image.h"
|
||||||
|
#include "stb_image_resize.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
image_t *image_load(FILE *file)
|
||||||
|
{
|
||||||
|
image_t *img = calloc(1, sizeof(image_t));
|
||||||
|
int n;
|
||||||
|
img->pixels = (rgba8 *)stbi_load_from_file(file,
|
||||||
|
&img->width, &img->height,
|
||||||
|
&n, STBI_rgb_alpha);
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
image_t *image_resize(image_t *img, int width, int height)
|
||||||
|
{
|
||||||
|
image_t *res = calloc(1, sizeof(image_t));
|
||||||
|
res->width = width;
|
||||||
|
res->height = height;
|
||||||
|
res->pixels = calloc(width * height, sizeof(rgba8));
|
||||||
|
stbir_resize_uint8((const unsigned char *)img->pixels,
|
||||||
|
img->width, img->height, 0,
|
||||||
|
(unsigned char *)res->pixels,
|
||||||
|
res->width, res->height, 0, STBI_rgb_alpha);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_unload(image_t *img)
|
||||||
|
{
|
||||||
|
free(img->pixels);
|
||||||
|
free(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_size_keep_aspect(int w, int h, int dw, int dh, int *ow, int *oh)
|
||||||
|
{
|
||||||
|
*ow = dw;
|
||||||
|
*oh = dh;
|
||||||
|
float ratio = (float)w / (float)h;
|
||||||
|
float ratio_dst = (float)dw / (float)dh;
|
||||||
|
int tmp_1, tmp_2;
|
||||||
|
if (ratio_dst >= ratio)
|
||||||
|
{
|
||||||
|
tmp_1 = floor(dh * ratio);
|
||||||
|
tmp_2 = ceil(dh * ratio);
|
||||||
|
if (fabsf(ratio - (float)tmp_1 / dh) < fabsf(ratio - (float)tmp_1 / dh))
|
||||||
|
*ow = tmp_1 < 1 ? 1 : tmp_1;
|
||||||
|
else
|
||||||
|
*ow = tmp_2 < 1 ? 1 : tmp_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_1 = floor(dw / ratio);
|
||||||
|
tmp_2 = ceil(dw / ratio);
|
||||||
|
if (tmp_2 == 0 ||
|
||||||
|
fabs(ratio - (float)dw / tmp_1) < fabs(ratio - (float)dw / tmp_2))
|
||||||
|
(*oh) = tmp_1 < 1 ? 1 : tmp_1;
|
||||||
|
else
|
||||||
|
(*oh) = tmp_2 < 1 ? 1 : tmp_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef _IMAGE_H_
|
||||||
|
#define _IMAGE_H_
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "colors.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int errno;
|
||||||
|
rgba8 *pixels;
|
||||||
|
} image_t;
|
||||||
|
|
||||||
|
image_t *image_load(FILE *file);
|
||||||
|
image_t *image_resize(image_t *img, int width, int height);
|
||||||
|
void image_unload(image_t *img);
|
||||||
|
|
||||||
|
void get_size_keep_aspect(int w, int h, int dw, int dh, int *ow, int *oh);
|
||||||
|
|
||||||
|
#endif
|
15
src/main.c
15
src/main.c
|
@ -1,11 +1,20 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "args.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
asc_args_t args;
|
||||||
(void)argv;
|
int res = parse_args(argc, argv, &args);
|
||||||
printf("ah shit, here we go again\n");
|
if (res == 1) return 0;
|
||||||
|
if (res < 0) return -res;
|
||||||
|
|
||||||
|
asc_state_t state;
|
||||||
|
res = prepare_state(argc, argv, args, &state);
|
||||||
|
if (res == 1) return 0;
|
||||||
|
if (res < 0) return -res;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "mod_blocks.h"
|
||||||
|
|
||||||
|
void mod_blocks_prepare(asc_state_t *state)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mod_blocks_main(asc_state_t state)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef _MOD_BLOCKS_
|
||||||
|
#define _MOD_BLOCKS_
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "colors.h"
|
||||||
|
#include "args.h"
|
||||||
|
|
||||||
|
void mod_blocks_prepare(asc_state_t *state);
|
||||||
|
void mod_blocks_main(asc_state_t state);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||||
|
#include "stb_image_resize.h"
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../thirdparty/stb/stb_image_resize.h"
|
Loading…
Reference in New Issue