Start mipmapping infrastructure

This commit is contained in:
Matthias Schiffer 2015-02-03 12:41:47 +01:00
parent b3c1a9be2f
commit e1b3347da5
4 changed files with 110 additions and 10 deletions

View file

@ -35,6 +35,7 @@
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <system_error>
#include <sys/types.h>
@ -46,8 +47,7 @@
#include <unistd.h>
using namespace MinedMap;
namespace MinedMap {
static const size_t DIM = World::Region::SIZE*World::Chunk::SIZE;
@ -85,7 +85,7 @@ static void doRegion(const std::string &input, const std::string &output) {
uint32_t image[DIM*DIM] = {};
World::Region::visitChunks(input.c_str(), [&image] (size_t X, size_t Z, const World::Chunk *chunk) { addChunk(image, X, Z, chunk); });
writePNG(tmpfile.c_str(), image, DIM, DIM);
PNG::write(tmpfile.c_str(), reinterpret_cast<const uint8_t*>(image), DIM, DIM);
struct timespec times[2] = {instat.st_mtim, instat.st_mtim};
if (utimensat(AT_FDCWD, tmpfile.c_str(), times, 0) < 0)
@ -116,7 +116,21 @@ static bool checkFilename(const char *name, int *x, int *z) {
}
static void makeDir(const std::string &name) {
if (mkdir(name.c_str(), 0777) < 0 && errno != EEXIST)
throw std::system_error(errno, std::generic_category(), "unable to create directory " + name);
}
static void makeMipmaps(const std::string &outputdir, const Info &info) {
}
}
int main(int argc, char *argv[]) {
using namespace MinedMap;
if (argc < 3) {
std::fprintf(stderr, "Usage: %s <data directory> <output directory>\n", argv[0]);
return 1;
@ -126,6 +140,9 @@ int main(int argc, char *argv[]) {
std::string regiondir = inputdir + "/region";
std::string outputdir(argv[2]);
std::string regionoutdir = outputdir + "/0";
makeDir(regionoutdir);
DIR *dir = opendir(regiondir.c_str());
if (!dir) {
@ -144,7 +161,7 @@ int main(int argc, char *argv[]) {
info.addRegion(x, z);
std::string name(entry->d_name);
doRegion(regiondir + "/" + name, outputdir + "/" + name.substr(0, name.length()-3) + "png");
doRegion(regiondir + "/" + name, regionoutdir + "/" + name.substr(0, name.length()-3) + "png");
}
closedir(dir);
@ -152,6 +169,8 @@ int main(int argc, char *argv[]) {
World::Level level((inputdir + "/level.dat").c_str());
info.setSpawn(level.getSpawn());
makeMipmaps(outputdir, info);
info.writeJSON((outputdir + "/info.json").c_str());
return 0;

View file

@ -28,17 +28,19 @@
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <system_error>
#include <png.h>
namespace MinedMap {
namespace PNG {
void writePNG(const char *filename, const uint32_t *data, size_t width, size_t height) {
void write(const char *filename, const uint8_t *data, size_t width, size_t height) {
std::FILE *f = std::fopen(filename, "wb");
if (!f)
throw std::system_error(errno, std::generic_category(), "unable to open output file");
throw std::system_error(errno, std::generic_category(), "unable to open PNG file");
png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr)
@ -63,13 +65,88 @@ void writePNG(const char *filename, const uint32_t *data, size_t width, size_t h
uint8_t *row_pointers[height];
for (size_t i = 0; i < height; i++)
row_pointers[i] = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&data[i*width]));
row_pointers[i] = const_cast<uint8_t*>(&data[4*i*width]);
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
std::fclose(f);
}
void read(const char *filename, uint8_t *data, size_t width, size_t height) {
std::FILE *f = std::fopen(filename, "rb");
if (!f)
throw std::system_error(errno, std::generic_category(), "unable to open PNG file");
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr)
throw std::runtime_error("unable to create PNG read struct");
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
throw std::runtime_error("unable to create PNG info struct");
}
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
throw std::runtime_error("unable to create PNG info struct");
}
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(f);
throw std::runtime_error("unable to read PNG file");
}
png_init_io(png_ptr, f);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
if (png_get_image_width(png_ptr, info_ptr) != width
|| png_get_image_height(png_ptr, info_ptr) != height
|| png_get_bit_depth(png_ptr, info_ptr) != 8
|| png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA)
longjmp(png_jmpbuf(png_ptr), 1);
uint8_t **row_pointers = png_get_rows(png_ptr, info_ptr);
for (size_t i = 0; i < height; i++)
std::memcpy(&data[4*i*width], row_pointers[i], 4*width);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
std::fclose(f);
}
static void readScaled(uint8_t *data, size_t offset_w, size_t offset_h, const char *file, size_t width, size_t height) {
if (!file)
return;
uint8_t input[4*width*height];
read(file, input, width, height);
for (size_t h = 0; h < width/2; h++) {
for (size_t w = 0; w < width/2; w++) {
for (size_t c = 0; c < 4; c++) {
size_t i = 8*width*h + 8*w + c;
data[4*width*(offset_h+h) + 4*(offset_w+w) + c] = (input[i] + input[i+4] + input[i+4*width] + input[i+4*width+4])/4;
}
}
}
}
void mipmap(const char *output, size_t width, size_t height, const char *nw, const char *ne, const char *sw, const char *se) {
uint8_t data[4*width*height];
std::memset(data, 0, sizeof(data));
readScaled(data, 0, 0, nw, width, height);
readScaled(data, width/2, 0, ne, width, height);
readScaled(data, 0, height/2, sw, width, height);
readScaled(data, width/2, height/2, se, width, height);
write(output, data, width, height);
}
}
}

View file

@ -31,7 +31,11 @@
namespace MinedMap {
namespace PNG {
void writePNG(const char *filename, const uint32_t *data, size_t width, size_t height);
void write(const char *filename, const uint8_t *data, size_t width, size_t height);
void read(const char *filename, uint8_t *data, size_t width, size_t height);
void mipmap(const char *output, size_t width, size_t height, const char *nw, const char *ne, const char *sw, const char *se);
}
}

View file

@ -21,7 +21,7 @@ var MinedMapLayer = L.GridLayer.extend({
if (coords.x >= this._info.minX && coords.x <= this._info.maxX &&
coords.y >= this._info.minZ && coords.y <= this._info.maxZ &&
this._regions[coords.y-this._info.minZ][coords.x-this._info.minX])
tile.src = 'data/r.'+coords.x+'.'+coords.y+'.png';
tile.src = 'data/0/r.'+coords.x+'.'+coords.y+'.png';
return tile;
},