forked from mirrors/principia
Add lvl-icon-extractor tool for extracting icon from level files
Rewritten from the original `level-screenshot-converter` Python script into C++ using Principia's own level reader and libpng directly
This commit is contained in:
parent
01236f4b31
commit
0051979187
5 changed files with 113 additions and 2 deletions
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS := lvledit progress-get
|
||||
SUBDIRS := lvl-icon-extractor lvledit progress-get
|
||||
|
||||
.PHONY: all clean $(SUBDIRS)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
This directory contains utility scripts and programs used for Principia development or for working with file formats.
|
||||
|
||||
## Scripts
|
||||
- `prepare_release_builds.sh`:
|
||||
- `prepare_release_builds.sh`: Download and prepare release builds when making a release
|
||||
- `set_version.lua`: Update the version number across the codebase when preparing a release (See [Making a Release](https://principia-web.se/wiki/Making_a_Release#incrementing-version-tagging)).
|
||||
- `update-sandbox-menu.sh`: Update the pre-rendered sandbox and item menu
|
||||
|
||||
## Programs
|
||||
Most of these programs rely on source files from the main Principia codebase and need to be compiled to run. Likely only works on Linux. You can use the `Makefile` in each directory or run `make` in the `utils` directory to build all of them.
|
||||
|
||||
- `lvl-icon-extractor`: Extract the embedded level icon in a Principia level file
|
||||
- `lvledit`: Edit metadata of Principia level files
|
||||
- `progress-get`: Get leaderboard score for a given level from a data.bin file
|
||||
|
|
|
|||
20
utils/lvl-icon-extractor/Makefile
Normal file
20
utils/lvl-icon-extractor/Makefile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
BIN = ../bin
|
||||
PRINCIPIA = ../..
|
||||
PROGRAM = lvl-icon-extractor
|
||||
SRCS := main.cc $(PRINCIPIA)/src/pkgman.cc $(PRINCIPIA)/src/rand.c
|
||||
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -D_NO_TMS -O2 -ffunction-sections -fdata-sections
|
||||
INCLUDES ?= -I$(PRINCIPIA)/src -I$(PRINCIPIA)/lib
|
||||
LDFLAGS ?= -lz -lpng -Wl,--gc-sections
|
||||
|
||||
all: $(BIN)/$(PROGRAM)
|
||||
|
||||
$(BIN)/$(PROGRAM): $(SRCS)
|
||||
@mkdir -p $(BIN)
|
||||
$(CXX) $(CXXFLAGS) $(INCLUDES) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm $(BIN)/$(PROGRAM)
|
||||
|
||||
.PHONY: all clean
|
||||
8
utils/lvl-icon-extractor/README.md
Normal file
8
utils/lvl-icon-extractor/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# `lvl-icon-extractor`
|
||||
Extract the embedded level icon (a 128x128 greyscale bitmap) from a Principia level file and save it as a PNG.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
lvl-icon-extractor <level path> <png output path>
|
||||
```
|
||||
82
utils/lvl-icon-extractor/main.cc
Normal file
82
utils/lvl-icon-extractor/main.cc
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <png.h>
|
||||
#include "pkgman.hh"
|
||||
|
||||
static lvledit lvl;
|
||||
|
||||
static int write_png(const char *outpath, uint8_t *icon, int width, int height) {
|
||||
FILE *fp = fopen(outpath, "wb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "could not open output file %s\n", outpath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "png_create_write_struct failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
fclose(fp);
|
||||
fprintf(stderr, "png_create_info_struct failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
fprintf(stderr, "libpng fatal error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
|
||||
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
// the level icon is stored upside down (GL coord style?), so let's just
|
||||
// write rows in reverse order here...
|
||||
png_bytep row = (png_bytep)(icon + (height - 1 - y) * width);
|
||||
png_write_row(png_ptr, row);
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "usage: lvl-icon-extractor <level_path> <out.png>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *path = argv[1];
|
||||
const char *out = argv[2];
|
||||
|
||||
if (!lvl.open_from_path(path)) {
|
||||
fprintf(stderr, "could not open file %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int ICON_W = 128;
|
||||
const int ICON_H = 128;
|
||||
|
||||
if (write_png(out, lvl.lvl.icon, ICON_W, ICON_H) != 0) {
|
||||
fprintf(stderr, "failed to write png %s\n", out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue