mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
PNG: add support for grayscale images without alpha
This commit is contained in:
parent
4f49434dbf
commit
dc97c4a8c1
3 changed files with 46 additions and 27 deletions
|
@ -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<const uint8_t*>(image.get()), true, intime);
|
||||
writeImage(output_light, lightmap.get(), false, intime);
|
||||
writeImage(output, reinterpret_cast<const uint8_t*>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
44
src/PNG.cpp
44
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<uint8_t*>(&data[(colored ? 4 : 2)*i*width]);
|
||||
row_pointers[i] = const_cast<uint8_t*>(&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<uint8_t[]> 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<uint8_t[]> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
13
src/PNG.hpp
13
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue