Skip to content

Commit

Permalink
Add a --tilesize option.
Browse files Browse the repository at this point in the history
The produces tiled output way faster than repeatedly using --geometry
because it only reads the databse once.
  • Loading branch information
Martijn Versteegh committed Nov 14, 2018
1 parent c382c2c commit bd0c140
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 24 deletions.
6 changes: 6 additions & 0 deletions Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,9 @@ void Image::save(const std::string &filename)
fclose(f);
#endif
}


void Image::fill(Color &c)
{
gdImageFilledRectangle(m_image, 0, 0, m_width - 1 , m_height - 1, color2int(c));
}
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ backend:
geometry:
Limit area to specific geometry (*x:z+w+h* where x and z specify the lower left corner), e.g. ``--geometry -800:-800+1600+1600``

tilesize:
Don't output one big image, but output tiles of the specified size, e.g. "--tilesize 128x128". The sizes will be rounded to
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.

zoom:
Apply zoom to drawn nodes by enlarging them to n*n squares, e.g. ``--zoom 4``

Expand Down
136 changes: 115 additions & 21 deletions TileGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ TileGenerator::TileGenerator():
m_geomY(-2048),
m_geomX2(2048),
m_geomY2(2048),
m_tileW(INT_MAX),
m_tileH(INT_MAX),
m_zoom(1),
m_scales(SCALE_LEFT | SCALE_TOP)
{
Expand Down Expand Up @@ -190,6 +192,13 @@ void TileGenerator::setGeometry(int x, int y, int w, int h)
m_geomY2 = round_multiple_nosign(y + h, 16) / 16;
}

void TileGenerator::setTileSize(int w, int h)
{
m_tileW = round_multiple_nosign(w, 16) / 16;
m_tileH = round_multiple_nosign(h, 16) / 16;
}


void TileGenerator::setMinY(int y)
{
m_yMin = y;
Expand Down Expand Up @@ -251,19 +260,66 @@ void TileGenerator::generate(const std::string &input, const std::string &output
}

createImage();
renderMap();
closeDatabase();
if (m_drawScale) {
renderScale();
}
if (m_drawOrigin) {
renderOrigin();


if (m_tileW < INT_MAX || m_tileH < INT_MAX)
{
tilePositions();

int trueXMin = m_xMin;
int trueZMin = m_zMin;

for (int x = 0; x < m_numTilesX; x++)
{
for (int y = 0; y < m_numTilesY; y++)
{
TileMap::iterator t = m_tiles.find(x + (y << 16));
m_xMin = trueXMin + x * m_tileW;
m_zMin = trueZMin + y * m_tileH;
m_xMax = m_xMin + m_tileW - 1;
m_zMax = m_zMin + m_tileH -1;

if (t != m_tiles.end() || !m_dontWriteEmpty)
{
m_image->fill(m_bgColor);
if (t != m_tiles.end())
renderMap(t->second);
if (m_drawScale) {
renderScale();
}
if (m_drawOrigin) {
renderOrigin();
}
if (m_drawPlayers) {
renderPlayers(input_path);
}
ostringstream fn;
fn << x << '_' << y << '_' << output;
writeImage(fn.str());
}
}
}
}
if (m_drawPlayers) {
renderPlayers(input_path);
else
{
m_image->fill(m_bgColor);
renderMap(m_positions);
if (m_drawScale) {
renderScale();
}
if (m_drawOrigin) {
renderOrigin();
}
if (m_drawPlayers) {
renderPlayers(input_path);
}
writeImage(output);
}
writeImage(output);
closeDatabase();
printUnknown();

delete m_image;
m_image = NULL;
}

void TileGenerator::parseColorsStream(std::istream &in)
Expand Down Expand Up @@ -380,8 +436,17 @@ void TileGenerator::createImage()
m_zMax = m_geomY2-1;
}

m_mapWidth = (m_xMax - m_xMin + 1) * 16;
m_mapHeight = (m_zMax - m_zMin + 1) * 16;
m_mapWidth = (m_xMax - m_xMin + 1);
m_mapHeight = (m_zMax - m_zMin + 1);

if (m_mapWidth > m_tileW)
m_mapWidth = m_tileW;

if (m_mapHeight > m_tileH)
m_mapHeight = m_tileH;

m_mapWidth *= 16;
m_mapHeight *= 16;

m_xBorder = (m_scales & SCALE_LEFT) ? scale_d : 0;
m_yBorder = (m_scales & SCALE_TOP) ? scale_d : 0;
Expand All @@ -401,15 +466,15 @@ void TileGenerator::createImage()
m_image->drawFilledRect(0, 0, image_width, image_height, m_bgColor); // Background
}

void TileGenerator::renderMap()
void TileGenerator::renderMap(PositionsList &positions)
{
BlockDecoder blk;
std::list<int> zlist = getZValueList();
std::list<int> zlist = getZValueList(positions);
for (std::list<int>::iterator zPosition = zlist.begin(); zPosition != zlist.end(); ++zPosition) {
int zPos = *zPosition;
std::map<int16_t, BlockList> blocks;
m_db->getBlocksOnZ(blocks, zPos);
for (std::list<std::pair<int, int> >::const_iterator position = m_positions.begin(); position != m_positions.end(); ++position) {
for (PositionsList::const_iterator position = positions.begin(); position != positions.end(); ++position) {
if (position->second != zPos)
continue;

Expand Down Expand Up @@ -637,9 +702,12 @@ void TileGenerator::renderPlayers(const std::string &inputPath)
{
PlayerAttributes players(inputPath);
for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) {
if (player->x < m_xMin * 16 || player->x > m_xMax * 16 ||
player->z < m_zMin * 16 || player->z > m_zMax * 16)
if (player->x < m_xMin*16 || player->x > m_xMax * 16 ||
player->z < m_zMin*16 || player->z > m_zMax * 16 )
{
continue;

}
if (player->y < m_yMin || player->y > m_yMax)
continue;
int imageX = getImageX(player->x, true),
Expand All @@ -651,10 +719,10 @@ void TileGenerator::renderPlayers(const std::string &inputPath)
}
}

inline std::list<int> TileGenerator::getZValueList() const
inline std::list<int> TileGenerator::getZValueList(PositionsList &positions) const
{
std::list<int> zlist;
for (std::list<std::pair<int, int> >::const_iterator position = m_positions.begin(); position != m_positions.end(); ++position)
for (PositionsList::const_iterator position = positions.begin(); position != positions.end(); ++position)
zlist.push_back(position->second);
zlist.sort();
zlist.unique();
Expand All @@ -665,8 +733,7 @@ inline std::list<int> TileGenerator::getZValueList() const
void TileGenerator::writeImage(const std::string &output)
{
m_image->save(output);
delete m_image;
m_image = NULL;
cout << "wrote image:" << output << endl;
}

void TileGenerator::printUnknown()
Expand Down Expand Up @@ -696,3 +763,30 @@ inline void TileGenerator::setZoomed(int x, int y, Color color)
{
m_image->drawFilledRect(getImageX(x), getImageY(y), m_zoom, m_zoom, color);
}


void TileGenerator::tilePositions()
{
m_numTilesX = round_multiple_nosign(m_xMax - m_xMin + 1, m_tileW) / m_tileW;
m_numTilesY = round_multiple_nosign(m_zMax - m_zMin + 1, m_tileH) / m_tileH;

for (PositionsList::iterator p = m_positions.begin(); p != m_positions.end(); p++)
{
int xtile = (p->first - m_xMin) / m_tileW;
int ytile = (p->second - m_zMin) / m_tileH;

int key = xtile + (ytile << 16);

TileMap::iterator t = m_tiles.find(key);

if (t == m_tiles.end())
{
PositionsList l;
m_tiles.insert(std::pair<int, PositionsList>(key, l));
t = m_tiles.find(key);
}

t->second.push_back(std::pair<int, int>(p->first, p->second));
}
}

1 change: 1 addition & 0 deletions include/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Image {
void drawFilledRect(int x, int y, int w, int h, const Color &c);
void drawCircle(int x, int y, int diameter, const Color &c);
void save(const std::string &filename);
void fill(Color &c);

private:
Image(const Image&);
Expand Down
19 changes: 16 additions & 3 deletions include/TileGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,20 @@ struct BitmapThing { // 16x16 bitmap
uint16_t val[16];
};

typedef std::list<std::pair<int, int> > PositionsList;


class TileGenerator
{
private:
#if __cplusplus >= 201103L
typedef std::unordered_map<std::string, ColorEntry> ColorMap;
typedef std::unordered_set<std::string> NameSet;
typedef std::unordered_map<int, PositionsList> TileMap;
#else
typedef std::map<std::string, ColorEntry> ColorMap;
typedef std::set<std::string> NameSet;
typedef std::map<int, PositionsList> TileMap;
#endif

public:
Expand All @@ -81,6 +85,7 @@ class TileGenerator
void setDrawAlpha(bool drawAlpha);
void setShading(bool shading);
void setGeometry(int x, int y, int w, int h);
void setTileSize(int w, int h);
void setMinY(int y);
void setMaxY(int y);
void parseColorsFile(const std::string &fileName);
Expand All @@ -90,15 +95,16 @@ class TileGenerator
void setZoom(int zoom);
void setScales(uint flags);
void setDontWriteEmpty(bool f);
void tilePositions();

private:
void parseColorsStream(std::istream &in);
void openDb(const std::string &input);
void closeDatabase();
void loadBlocks();
void createImage();
void renderMap();
std::list<int> getZValueList() const;
void renderMap(PositionsList &positions);
std::list<int> getZValueList(PositionsList &positions) const;
void renderMapBlock(const BlockDecoder &blk, const BlockPos &pos);
void renderMapBlockBottom(const BlockPos &pos);
void renderShading(int zPos);
Expand Down Expand Up @@ -138,16 +144,23 @@ class TileGenerator
int m_geomY;
int m_geomX2;
int m_geomY2;
int m_tileW;
int m_tileH;
int m_mapWidth;
int m_mapHeight;
std::list<std::pair<int, int> > m_positions;

ColorMap m_colorMap;
BitmapThing m_readPixels;
BitmapThing m_readInfo;
NameSet m_unknownNodes;
Color m_color[16][16];
uint8_t m_thickness[16][16];

PositionsList m_positions;

TileMap m_tiles;
int m_numTilesX, m_numTilesY;

int m_zoom;
uint m_scales;
}; // class TileGenerator
Expand Down
14 changes: 14 additions & 0 deletions mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void usage()
" --max-y <y>\n"
" --backend <backend>\n"
" --geometry x:y+w+h\n"
" --tilesize wxh\n"
" --extent\n"
" --zoom <zoomlevel>\n"
" --colors <colors.txt>\n"
Expand Down Expand Up @@ -82,6 +83,7 @@ int main(int argc, char *argv[])
{"noshading", no_argument, 0, 'H'},
{"backend", required_argument, 0, 'd'},
{"geometry", required_argument, 0, 'g'},
{"tilesize", required_argument, 0, 't'},
{"extent", no_argument, 0, 'E'},
{"min-y", required_argument, 0, 'a'},
{"max-y", required_argument, 0, 'c'},
Expand Down Expand Up @@ -174,6 +176,18 @@ int main(int argc, char *argv[])
generator.setGeometry(x, y, w, h);
}
break;
case 't': {
std::istringstream geometry(optarg);
int w, h;
char c;
geometry >> w >> c >> h;
if (geometry.fail() || c != 'x' || w < 1 || h < 1) {
usage();
exit(1);
}
generator.setTileSize(w, h);
}
break;
case 'f': {
uint flags = 0;
if(strchr(optarg, 't') != NULL)
Expand Down
6 changes: 6 additions & 0 deletions minetestmapper.6
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ Use specific map backend; supported: *sqlite3*, *leveldb*, *redis*, *postgresql*
.BR \-\-geometry " " \fIgeometry\fR
Limit area to specific geometry (*x:y+w+h* where x and y specify the lower left corner), e.g. "--geometry -800:-800+1600+1600"

.TP
.BR \-\-tilesize " " \fItilesize\fR
Don't output one big image, but output tiles of the specified size, e.g. "--tilesize 128x128". The sizes will be rounded to
a multiple of 16. The filenames will be created in the form <x>_<y>_<filename>, where <x> and <y>
are the tile numbers and <filename> is the name specified with -o. Skip empty tiles by also specifying --noemptyimage.

.TP
.BR \-\-extent " " \fIextent\fR
Dont render the image, just print the extent of the map that would be generated, in the same format as the geometry above.
Expand Down

0 comments on commit bd0c140

Please sign in to comment.