diff --git a/src/MinedMap.cpp b/src/MinedMap.cpp index 32ed61f..aafcf0e 100644 --- a/src/MinedMap.cpp +++ b/src/MinedMap.cpp @@ -87,11 +87,11 @@ static void writeStamp(const std::string &filename, int64_t v) { } } -static void writeImage(const std::string &output, const uint8_t *data, bool colored, int64_t t) { +static void writeImage(const std::string &output, const uint8_t *data, PNG::Format format, int64_t t) { const std::string tmpfile = output + ".tmp"; try { - PNG::write(tmpfile.c_str(), data, DIM, DIM, colored); + PNG::write(tmpfile.c_str(), data, DIM, DIM, format); if (std::rename(tmpfile.c_str(), output.c_str()) < 0) { std::fprintf(stderr, "Unable to save %s: %s\n", output.c_str(), std::strerror(errno)); @@ -146,8 +146,8 @@ static void doRegion(const std::string &input, const std::string &output, const World::Region::visitChunks(input.c_str(), [&] (size_t X, size_t Z, const World::ChunkData *chunk) { addChunk(image.get(), lightmap.get(), X, Z, chunk); }); - writeImage(output, reinterpret_cast(image.get()), true, intime); - writeImage(output_light, lightmap.get(), false, intime); + writeImage(output, reinterpret_cast(image.get()), PNG::RGB_ALPHA, intime); + writeImage(output_light, lightmap.get(), PNG::GRAY_ALPHA, intime); } catch (const std::exception& ex) { std::fprintf(stderr, "Failed to generate %s: %s\n", output.c_str(), ex.what()); } @@ -203,7 +203,7 @@ static void makeMaps(const std::string ®iondir, const std::string &outputdir, } } -static bool makeMipmap(const std::string &dir, size_t level, size_t x, size_t z, bool colored) { +static bool makeMipmap(const std::string &dir, size_t level, size_t x, size_t z, PNG::Format imageFormat) { bool ret = false; std::string indir = dir + "/" + format(level-1) + "/"; @@ -254,7 +254,7 @@ static bool makeMipmap(const std::string &dir, size_t level, size_t x, size_t z, const std::string tmpfile = output + ".tmp"; try { - PNG::mipmap(tmpfile.c_str(), DIM, DIM, colored, nw, ne, sw, se); + PNG::mipmap(tmpfile.c_str(), DIM, DIM, imageFormat, nw, ne, sw, se); if (std::rename(tmpfile.c_str(), output.c_str()) < 0) { std::fprintf(stderr, "Unable to save %s: %s\n", output.c_str(), std::strerror(errno)); @@ -287,10 +287,10 @@ static void makeMipmaps(const std::string &dir, Info *info) { for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z++) { - if (makeMipmap(dir + "/map", level, x, z, true)) + if (makeMipmap(dir + "/map", level, x, z, PNG::RGB_ALPHA)) info->addRegion(x, z, level); - makeMipmap(dir + "/light", level, x, z, false); + makeMipmap(dir + "/light", level, x, z, PNG::GRAY_ALPHA); } } } diff --git a/src/PNG.cpp b/src/PNG.cpp index ad52564..ddc93a7 100644 --- a/src/PNG.cpp +++ b/src/PNG.cpp @@ -38,7 +38,19 @@ namespace MinedMap { namespace PNG { -void write(const char *filename, const uint8_t *data, size_t width, size_t height, bool colored) { +static const int formatColorTypes[] = { + [RGB_ALPHA] = PNG_COLOR_TYPE_RGB_ALPHA, + [GRAY_ALPHA] = PNG_COLOR_TYPE_GRAY_ALPHA, + [GRAY] = PNG_COLOR_TYPE_GRAY, +}; + +static const size_t formatBytes[] = { + [RGB_ALPHA] = 4, + [GRAY_ALPHA] = 2, + [GRAY] = 1, +}; + +void write(const char *filename, const uint8_t *data, size_t width, size_t height, Format format) { std::FILE *f = std::fopen(filename, "wb"); if (!f) throw std::system_error(errno, std::generic_category(), "unable to open PNG file"); @@ -61,12 +73,12 @@ void write(const char *filename, const uint8_t *data, size_t width, size_t heigh png_init_io(png_ptr, f); - png_set_IHDR(png_ptr, info_ptr, width, height, 8, colored ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY_ALPHA, + png_set_IHDR(png_ptr, info_ptr, width, height, 8, formatColorTypes[format], PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); uint8_t *row_pointers[height]; for (size_t i = 0; i < height; i++) - row_pointers[i] = const_cast(&data[(colored ? 4 : 2)*i*width]); + row_pointers[i] = const_cast(&data[formatBytes[format]*i*width]); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); @@ -75,7 +87,7 @@ void write(const char *filename, const uint8_t *data, size_t width, size_t heigh std::fclose(f); } -void read(const char *filename, uint8_t *data, size_t width, size_t height, bool colored) { +void read(const char *filename, uint8_t *data, size_t width, size_t height, Format format) { std::FILE *f = std::fopen(filename, "rb"); if (!f) throw std::system_error(errno, std::generic_category(), "unable to open PNG file"); @@ -109,25 +121,25 @@ void read(const char *filename, uint8_t *data, size_t width, size_t height, bool 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) != (colored ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY_ALPHA)) + || png_get_color_type(png_ptr, info_ptr) != formatColorTypes[format]) 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[(colored ? 4 : 2)*i*width], row_pointers[i], (colored ? 4 : 2)*width); + std::memcpy(&data[formatBytes[format]*i*width], row_pointers[i], formatBytes[format]*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, bool colored) { +static void readScaled(uint8_t *data, size_t offset_w, size_t offset_h, const char *file, size_t width, size_t height, Format format) { if (!file) return; - size_t b = (colored ? 4 : 2); + size_t b = formatBytes[format]; std::unique_ptr input(new uint8_t[b*width*height]); - read(file, input.get(), width, height, colored); + read(file, input.get(), width, height, format); for (size_t h = 0; h < width/2; h++) { for (size_t w = 0; w < width/2; w++) { @@ -139,17 +151,17 @@ static void readScaled(uint8_t *data, size_t offset_w, size_t offset_h, const ch } } -void mipmap(const char *output, size_t width, size_t height, bool colored, const char *nw, const char *ne, const char *sw, const char *se) { - size_t size = (colored ? 4 : 2)*width*height; +void mipmap(const char *output, size_t width, size_t height, Format format, const char *nw, const char *ne, const char *sw, const char *se) { + size_t size = formatBytes[format]*width*height; std::unique_ptr data(new uint8_t[size]); std::memset(data.get(), 0, size); - readScaled(data.get(), 0, 0, nw, width, height, colored); - readScaled(data.get(), width/2, 0, ne, width, height, colored); - readScaled(data.get(), 0, height/2, sw, width, height, colored); - readScaled(data.get(), width/2, height/2, se, width, height, colored); + readScaled(data.get(), 0, 0, nw, width, height, format); + readScaled(data.get(), width/2, 0, ne, width, height, format); + readScaled(data.get(), 0, height/2, sw, width, height, format); + readScaled(data.get(), width/2, height/2, se, width, height, format); - write(output, data.get(), width, height, colored); + write(output, data.get(), width, height, format); } } diff --git a/src/PNG.hpp b/src/PNG.hpp index ee6ffd4..3780bbe 100644 --- a/src/PNG.hpp +++ b/src/PNG.hpp @@ -33,9 +33,16 @@ namespace MinedMap { namespace PNG { -void write(const char *filename, const uint8_t *data, size_t width, size_t height, bool colored); -void read(const char *filename, uint8_t *data, size_t width, size_t height, bool colored); -void mipmap(const char *output, size_t width, size_t height, bool colored, const char *nw, const char *ne, const char *sw, const char *se); +enum Format { + RGB_ALPHA, + GRAY_ALPHA, + GRAY, + +}; + +void write(const char *filename, const uint8_t *data, size_t width, size_t height, Format format); +void read(const char *filename, uint8_t *data, size_t width, size_t height, Format format); +void mipmap(const char *output, size_t width, size_t height, Format format, const char *nw, const char *ne, const char *sw, const char *se); } }