asset pipeline?
This commit is contained in:
parent
7ca0d351f7
commit
5e3b3c2bf9
@ -26,9 +26,12 @@ deps := $(wildcard out/*.d)
|
|||||||
.PHONY: all res bin run clean
|
.PHONY: all res bin run clean
|
||||||
|
|
||||||
all: res bin
|
all: res bin
|
||||||
|
|
||||||
bin: ${ns}/${NAME}.${EXTENSION}
|
bin: ${ns}/${NAME}.${EXTENSION}
|
||||||
run: ${ns}/${NAME}.${EXTENSION}
|
res: out/${NAME}.assets
|
||||||
$<
|
|
||||||
|
run: ${ns}/${NAME}.${EXTENSION} out/${NAME}.assets
|
||||||
|
$^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
${RM} -r ${ns}/
|
${RM} -r ${ns}/
|
||||||
@ -45,7 +48,7 @@ ${ns}/%.o: src/%.c++ | ${ns}/
|
|||||||
%/:
|
%/:
|
||||||
@${MKDIR} $@
|
@${MKDIR} $@
|
||||||
|
|
||||||
#include assets.mk
|
include assets.mk
|
||||||
|
|
||||||
ifeq ($(filter clean mostlyclean,${MAKECMDGOALS}),)
|
ifeq ($(filter clean mostlyclean,${MAKECMDGOALS}),)
|
||||||
include ${deps}
|
include ${deps}
|
||||||
|
|||||||
35
assets.mk
Normal file
35
assets.mk
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
PRITE ?= libresprite
|
||||||
|
|
||||||
|
glsl := $(wildcard src/*.glsl)
|
||||||
|
frag := $(wildcard src/*.frag)
|
||||||
|
#shaders := ${glsl:src/%.glsl=out/%.shader} ${frag:src/%.frag=out/%.shader}
|
||||||
|
shaders := $(patsubst src/%,out/%.shader,${glsl:.glsl=} ${frag:.frag=})
|
||||||
|
pictures := $(patsubst src/%.ase,out/%.picture, $(wildcard src/*.ase))
|
||||||
|
|
||||||
|
out/suwi.assets: ${shaders} ${pictures} | out/assetsmk
|
||||||
|
printf '%s\0' $^ | sed -nz 'p;s:.*/::p' | $| -c0f out/suwi.assets -F - -N -
|
||||||
|
|
||||||
|
out/%.shader: src/%.glsl utl/vert.awk utl/frag.awk
|
||||||
|
awk -f utl/vert.awk $< > $@
|
||||||
|
printf '\0' >> $@
|
||||||
|
awk -f utl/frag.awk $< >> $@
|
||||||
|
printf '\0' >> $@
|
||||||
|
|
||||||
|
out/%.shader: src/%.frag utl/vert.awk utl/frag.awk src/default.glsl
|
||||||
|
awk -f utl/vert.awk src/default.glsl > $@
|
||||||
|
printf '\0' >> $@
|
||||||
|
cat $< >> $@
|
||||||
|
printf '\0' >> $@
|
||||||
|
|
||||||
|
out/%.png: src/%.ase
|
||||||
|
${PRITE} -b $< --save-as $@
|
||||||
|
|
||||||
|
out/%.picture: out/picmake out/%.png
|
||||||
|
$^ -o $@
|
||||||
|
|
||||||
|
|
||||||
|
out/picmake: utl/picmake.c
|
||||||
|
${CC} -o $@ $< -lpng
|
||||||
|
|
||||||
|
out/assetsmk: utl/assetsmk.c src/assread.c src/asswrite.c
|
||||||
|
${CC} -o $@ $^ -lz -I src/
|
||||||
@ -200,6 +200,9 @@ int assets_load(FILE *file, char const *name) {
|
|||||||
|
|
||||||
struct pack_result res = guilotine(pictures.rect.data(), pictures.rect.size(), 512, 1);
|
struct pack_result res = guilotine(pictures.rect.data(), pictures.rect.size(), 512, 1);
|
||||||
if (res.bins == 0) {
|
if (res.bins == 0) {
|
||||||
|
if (pictures.rect.size() == 0) {
|
||||||
|
fprintf(stderr, "error: %s: no textures?? lmao\n", name);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
src/suwi.ase
Normal file
BIN
src/suwi.ase
Normal file
Binary file not shown.
368
utl/assetsmk.c
Normal file
368
utl/assetsmk.c
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include "ass.h"
|
||||||
|
|
||||||
|
#if defined(__unix__)
|
||||||
|
#include <unistd.h>
|
||||||
|
#if defined(_POSIX_VERSION)
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct blob {
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void blob_free(struct blob *const blob);
|
||||||
|
|
||||||
|
// on error blob.data == NULL
|
||||||
|
static struct blob load_file(FILE *file);
|
||||||
|
|
||||||
|
struct ctx {
|
||||||
|
char **args;
|
||||||
|
FILE *assets;
|
||||||
|
FILE *names;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *read_one_line(FILE *file);
|
||||||
|
|
||||||
|
int verbose = 0, zero = 0;
|
||||||
|
|
||||||
|
void create_cb(char *restrict *filename, void *restrict *filedata, size_t *restrict filesize, void *restrict ctx_) {
|
||||||
|
struct ctx *ctx = ctx_;
|
||||||
|
free(*filename);
|
||||||
|
free(*filedata);
|
||||||
|
if (filesize == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (*ctx->args == NULL && ctx->assets == NULL) {
|
||||||
|
*filename = NULL;
|
||||||
|
*filedata = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (*ctx->args != NULL) {
|
||||||
|
*filename = strdup(*ctx->args++);
|
||||||
|
FILE *file = fopen(*filename, "rb");
|
||||||
|
if (file == NULL) {
|
||||||
|
perror(*filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct blob data = load_file(file);
|
||||||
|
if (data.data == NULL) {
|
||||||
|
perror(*filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*filedata = data.data;
|
||||||
|
*filesize = data.size;
|
||||||
|
} else {
|
||||||
|
*filename = read_one_line(ctx->assets);
|
||||||
|
if (*filename == NULL) {
|
||||||
|
*filedata = NULL;
|
||||||
|
if (ctx->names != NULL) {
|
||||||
|
char *n = read_one_line(ctx->names);
|
||||||
|
if (n != NULL) {
|
||||||
|
fputs("more names than paths\n", stderr);
|
||||||
|
free(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FILE *file = fopen(*filename, "rb");
|
||||||
|
if (file == NULL) {
|
||||||
|
perror(*filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct blob data = load_file(file);
|
||||||
|
if (data.data == NULL) {
|
||||||
|
perror(*filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ctx->names != NULL) {
|
||||||
|
char *name = read_one_line(ctx->names);
|
||||||
|
if (name == NULL) {
|
||||||
|
fputs("more paths than names\n", stderr);
|
||||||
|
ctx->names = NULL;
|
||||||
|
} else {
|
||||||
|
free(*filename);
|
||||||
|
*filename = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*filedata = data.data;
|
||||||
|
*filesize = data.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int extract_cb(char const *restrict filename, size_t length, void const *restrict data, size_t size, void *restrict ctx_) {
|
||||||
|
return 1; // todo
|
||||||
|
struct ctx *ctx = ctx_;
|
||||||
|
#if defined (_POSIX_VERSION)
|
||||||
|
open(*ctx->args++, O_WRONLY | O_EXCL | O_CREAT, 0666);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_cb(char const *restrict filename, size_t length, void const *restrict data, size_t size, void *restrict ctx_) {
|
||||||
|
struct ctx *ctx = ctx_;
|
||||||
|
if (*ctx->args != NULL || ctx->assets || ctx->names) {
|
||||||
|
fputs("--list does not take arguments\n", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (zero && verbose) {
|
||||||
|
fputs("--list doesnt support --verbose and --nul at the same time\n", stderr);
|
||||||
|
return 1;
|
||||||
|
} else if (zero) {
|
||||||
|
fwrite(filename, 1, length + 1, stdout);
|
||||||
|
} else if (verbose) {
|
||||||
|
fprintf(stdout, "%zu\t%s\n", size, filename);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "%s\n", filename);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
struct option const options[] = {
|
||||||
|
{"help", 0, NULL, 'h'},
|
||||||
|
{"verbose", 0, NULL, 'v'},
|
||||||
|
{"nul", 0, NULL, '0'},
|
||||||
|
{"create", 0, NULL, 'c'},
|
||||||
|
{"extract", 0, NULL, 'x'},
|
||||||
|
{"list", 0, NULL, 'l'},
|
||||||
|
{"file", 1, NULL, 'f'},
|
||||||
|
{"files", 1, NULL, 'F'},
|
||||||
|
{"names", 1, NULL, 'N'},
|
||||||
|
{NULL, 0, NULL, 0 },
|
||||||
|
};
|
||||||
|
int opt, fail = 0;
|
||||||
|
enum {
|
||||||
|
A_NONE,
|
||||||
|
A_CREATE,
|
||||||
|
A_EXTRACT,
|
||||||
|
A_LIST,
|
||||||
|
} action = A_NONE;
|
||||||
|
char *filename = NULL;
|
||||||
|
FILE *assets = NULL, *names = NULL;
|
||||||
|
while ((opt = getopt_long(argc, argv, "hv0cxlf:F:N:", options, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
fprintf(stderr, "usage: %s [-h | -c | -l | -x] [-0v] [-f ASSET_FILE] [-F PATHS] [-N NAMES]\n", argv[0]);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
fputs("-h --help this message\n", stderr);
|
||||||
|
fputs("-c --create create an asset pack\n", stderr);
|
||||||
|
fputs("-l --list list files in an asset pack\n", stderr);
|
||||||
|
fputs("-x --extract extract files from an asset pack\n", stderr);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
fputs("-0 --nul entries are NUL-separated (for use with -l -F -N)\n", stderr);
|
||||||
|
fputs("-v --verbose\n", stderr);
|
||||||
|
fputs("\t(-c) print names of files put in the pack\n", stderr);
|
||||||
|
fputs("\t(-l) print sizes of files in the pack\n", stderr);
|
||||||
|
fputs("\t(-x) print files extracted from the pack\n", stderr);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
fputs("-f --file=FILE file to use as the asset pack\n", stderr);
|
||||||
|
fputs("-F --files=FILE file containing the list of files to put in/extract from the asset pack\n", stderr);
|
||||||
|
fputs("-N --names=FILE file containing the list of names to use for the files (-c only)\n", stderr);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
fputs("-F and -N may both be \"-\", if stdin contains the paths and names interleaved\n", stderr);
|
||||||
|
return 0;
|
||||||
|
case 'v':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
zero = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
action = A_CREATE;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
action = A_EXTRACT;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
action = A_LIST;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
filename = optarg;
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (strcmp(optarg, "-")) {
|
||||||
|
if ((assets = fopen(optarg, "rb")) == NULL) {
|
||||||
|
perror(optarg);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assets = stdin;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
if (strcmp(optarg, "-")) {
|
||||||
|
if ((names = fopen(optarg, "rb")) == NULL) {
|
||||||
|
perror(optarg);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
names = stdin;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FILE *file;
|
||||||
|
if (action == A_CREATE) {
|
||||||
|
if (filename == NULL || strcmp(filename, "-") == 0) {
|
||||||
|
file = stdout;
|
||||||
|
} else {
|
||||||
|
file = fopen(filename, "wb");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (filename == NULL || strcmp(filename, "-") == 0) {
|
||||||
|
file = stdin;
|
||||||
|
} else {
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file == NULL) {
|
||||||
|
perror(filename);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
if (file == stdin && (assets == stdin || names == stdin)) {
|
||||||
|
fputs("not enough stdins, try `-f'\n", stderr);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
if (assets == NULL && names != NULL) {
|
||||||
|
fputs("-N is useless without -F\n", stderr);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
if (optind != argc && assets != NULL) {
|
||||||
|
fputs("mixing -F and arguments is not supported\n", stderr);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
if (fail) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct ctx ctx = {
|
||||||
|
.args = argv + optind,
|
||||||
|
.assets = assets,
|
||||||
|
.names = names,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
switch (action) {
|
||||||
|
case A_CREATE:
|
||||||
|
ret = asswrite(file, create_cb, &ctx);
|
||||||
|
break;
|
||||||
|
case A_EXTRACT:
|
||||||
|
#if !defined(_POSIX_VERSION)
|
||||||
|
if (optind == argc && assets == NULL) {
|
||||||
|
fputs("cannot use --extract without specifying any files\n(as a safety measure, specifying no files would prevent overwriting existing files, but this safety measure is not available in this version of the program, please use --list)\n", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ret = assread(file, extract_cb, &ctx);
|
||||||
|
break;
|
||||||
|
case A_LIST:
|
||||||
|
ret = assread(file, list_cb, &ctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
switch (ret) {
|
||||||
|
case ASS_OK:
|
||||||
|
return 0;
|
||||||
|
case ASS_BAD:
|
||||||
|
fputs("not an asset pack, or its corrupt\n", stderr);
|
||||||
|
return ASS_BAD;
|
||||||
|
case ASS_USER:
|
||||||
|
return ASS_USER; // the callback printed its own error message, probably
|
||||||
|
case ASS_TRUNC:
|
||||||
|
fputs("truncated asset pack\n", stderr);
|
||||||
|
return ASS_TRUNC;
|
||||||
|
case ASS_MEM:
|
||||||
|
fputs("failed to allocate memory\n", stderr);
|
||||||
|
return ASS_MEM;
|
||||||
|
case ASS_LAZY:
|
||||||
|
fputs("some kind of failure which i could theoretically handle, but it would make the code more complicated than i want it to be, has occured\n", stderr);
|
||||||
|
return ASS_LAZY;
|
||||||
|
case ASS_UNSUPPORTED:
|
||||||
|
fputs("unsupported version\n", stderr);
|
||||||
|
return ASS_UNSUPPORTED;
|
||||||
|
default:
|
||||||
|
fputs("unknown error\n", stderr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blob_free(struct blob *const blob) {
|
||||||
|
free(blob->data);
|
||||||
|
blob->data = NULL;
|
||||||
|
blob->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct blob load_file(FILE *file) {
|
||||||
|
const size_t START_SIZE = 8192;
|
||||||
|
char *data = malloc(START_SIZE);
|
||||||
|
size_t allocated = START_SIZE;
|
||||||
|
size_t used = 0;
|
||||||
|
while (1) {
|
||||||
|
size_t read = fread(data + used, 1, allocated - used, file);
|
||||||
|
if (read != allocated - used) {
|
||||||
|
used += read;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
used += read;
|
||||||
|
allocated *= 2;
|
||||||
|
void *const newdata = realloc(data, allocated);
|
||||||
|
if (newdata == NULL) {
|
||||||
|
goto realloc_error;
|
||||||
|
}
|
||||||
|
data = newdata;
|
||||||
|
}
|
||||||
|
if (used == 0) {
|
||||||
|
//free(data);
|
||||||
|
fclose(file);
|
||||||
|
return (struct blob) {.data = data, .size = 0};
|
||||||
|
}
|
||||||
|
void *const newdata = realloc(data, used);
|
||||||
|
if (newdata == NULL) {
|
||||||
|
goto realloc_error;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return (struct blob) {.data = newdata, .size = used};
|
||||||
|
|
||||||
|
realloc_error:
|
||||||
|
free(data);
|
||||||
|
fclose(file);
|
||||||
|
return (struct blob) {.data = NULL};
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *read_one_line(FILE *file) {
|
||||||
|
size_t allocated = 32;
|
||||||
|
size_t used = 0;
|
||||||
|
char *buf = malloc(allocated);
|
||||||
|
while (1) {
|
||||||
|
int c = fgetc(file);
|
||||||
|
if ((c == EOF && used == 0) || (c == '\0' && zero == 0)) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (used >= allocated) {
|
||||||
|
allocated *= 2;
|
||||||
|
if (allocated == 0) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *tmp = realloc(buf, allocated);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = tmp;
|
||||||
|
}
|
||||||
|
if (c == (zero? '\0': '\n') || c == EOF) {
|
||||||
|
buf[used] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
buf[used++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
utl/frag.awk
Executable file
12
utl/frag.awk
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env -S awk -f
|
||||||
|
|
||||||
|
BEGIN {mode = "any"; lineno = 1;}
|
||||||
|
|
||||||
|
{lineno++;}
|
||||||
|
|
||||||
|
/@@/ {mode = "any"; $0 = ("#line " lineno);}
|
||||||
|
/%%/ {mode = "vert";}
|
||||||
|
/##/ {mode = "frag"; $0 = ("#line " lineno);}
|
||||||
|
|
||||||
|
mode == "any"
|
||||||
|
mode == "frag"
|
||||||
148
utl/picmake.c
Normal file
148
utl/picmake.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
static char const pic_sig[8] = {'\xdd', '\xdd', 'p', 'i', 'c', '\n', '\0', 0};
|
||||||
|
static char const help_text[] = "%s [-fh] [-o OUTPUT.dat] INPUT.png\n";
|
||||||
|
|
||||||
|
static void write_vlq(size_t value, FILE *file) {
|
||||||
|
unsigned char buf[9];
|
||||||
|
size_t bytes;
|
||||||
|
for (bytes = 0; bytes < sizeof (size_t); bytes++) {
|
||||||
|
size_t byte = value >> (bytes * 8);
|
||||||
|
if ((byte & (0x7f >> bytes)) == byte) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[8 - bytes] = value >> (bytes * 8);
|
||||||
|
}
|
||||||
|
buf[8 - bytes] = (value >> (bytes * 8)) | (0xff00 >> bytes);
|
||||||
|
|
||||||
|
fwrite(buf + 8 - bytes, 1, bytes + 1, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
struct option const options[] = {
|
||||||
|
{"force", 0, NULL, 'f'},
|
||||||
|
{"help", 0, NULL, 'h'},
|
||||||
|
{"output", 1, NULL, 'o'},
|
||||||
|
{"verbose", 0, NULL, 'v'},
|
||||||
|
{NULL, 0, NULL, 0 },
|
||||||
|
};
|
||||||
|
int opt, force = 0, verbose = 0;
|
||||||
|
char *outname = NULL;
|
||||||
|
while ((opt = getopt_long(argc, argv, "fho:v", options, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
force++;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
fprintf(stderr, help_text, argv[0]);
|
||||||
|
fputs("-f --force allow outputting not-quite-successful conversions\n", stderr);
|
||||||
|
fputs("-h --help this message\n", stderr);
|
||||||
|
fputs("-o --output=FILE output converted image to FILE\n", stderr);
|
||||||
|
fputs("-v --verbose print diagnostics\n", stderr);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case 'o':
|
||||||
|
outname = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optind + 1 != argc) {
|
||||||
|
fprintf(stderr, help_text, argv[0]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// half-assed libpng use, will be fixed in a project where proper libpng use is necessary
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL);
|
||||||
|
if (png_ptr == NULL) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL) {
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
FILE *fp = NULL;
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
if (fp != NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fp = fopen(argv[optind], "rb");
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror(argv[optind]);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
|
||||||
|
// we do NOT want gamma!
|
||||||
|
//png_set_gamma_fixed(png_ptr, PNG_GAMMA_LINEAR, PNG_GAMMA_LINEAR);
|
||||||
|
//png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_LINEAR);
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bit_depth, color_type;
|
||||||
|
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||||
|
png_set_palette_to_rgb(png_ptr);
|
||||||
|
} else if (bit_depth < 8) {
|
||||||
|
png_set_packing(png_ptr);
|
||||||
|
} else if (bit_depth > 8) {
|
||||||
|
png_set_scale_16(png_ptr);
|
||||||
|
}
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||||
|
png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
} else {
|
||||||
|
png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
|
}
|
||||||
|
png_set_rgb_to_gray(png_ptr, 1, -1, -1);
|
||||||
|
//png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||||
|
png_bytepp row_pointers = malloc(sizeof (png_bytep) * height);
|
||||||
|
unsigned char *image = malloc(rowbytes * height);
|
||||||
|
for (unsigned i = 0; i < height; i++) {
|
||||||
|
row_pointers[i] = image + (height - i - 1) * rowbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_read_image(png_ptr, row_pointers);
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
//free(row_pointers);
|
||||||
|
|
||||||
|
if (outname != NULL) {
|
||||||
|
FILE *out = fopen(outname, "wb");
|
||||||
|
if (out == NULL) {
|
||||||
|
perror(outname);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fwrite(pic_sig, 1, sizeof (pic_sig), out);
|
||||||
|
write_vlq(width - 1, out);
|
||||||
|
write_vlq(height - 1, out);
|
||||||
|
for (size_t i = 0; i < width * height; i++) {
|
||||||
|
if (image[i * 2 + 1] < 0x80) {
|
||||||
|
fputc(0x00, out);
|
||||||
|
} else if (image[i * 2 + 0] < 0x80) {
|
||||||
|
fputc(0x80, out);
|
||||||
|
} else {
|
||||||
|
fputc(0xff, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
12
utl/vert.awk
Executable file
12
utl/vert.awk
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env -S awk -f
|
||||||
|
|
||||||
|
BEGIN {mode = "any"; lineno = 1;}
|
||||||
|
|
||||||
|
{lineno++;}
|
||||||
|
|
||||||
|
/@@/ {mode = "any"; $0 = ("#line " lineno);}
|
||||||
|
/%%/ {mode = "vert"; $0 = ("#line " lineno);}
|
||||||
|
/##/ {mode = "frag";}
|
||||||
|
|
||||||
|
mode == "any"
|
||||||
|
mode == "vert"
|
||||||
Loading…
x
Reference in New Issue
Block a user