Skip to content

Commit

Permalink
v5, saves images in exported_images folder, works with invalid OTB-OT…
Browse files Browse the repository at this point in the history
…BM versions
  • Loading branch information
gesior committed Jan 7, 2021
1 parent bd388c4 commit 1138730
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 137 deletions.
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,11 @@ GENERATE PNG IMAGES FROM OTBM
OTClient will report progress in terminal.

9. Your map images will appear in your system 'user' directory
9. Your map images will appear in OTClient directory

**%HOMEPATH%/otclient** - Windows, open it in folder explorer

**${HOME}/.otclient** - Linux, 'cd' to it, this folder is invisible, but you can navigate to it
**exported_images/map** - open it in folder explorer

10. Copy folder **map** from folder user's directory to folder **website_and_php_files** of otclient_mapgen.
10. Copy directory **map** from **exported_images** directory to directory **website_and_php_files** of otclient_mapgen.

--- NEXT STEPS REQUIRE **PHP** INSTALLED IN SYSTEM ---

Expand Down Expand Up @@ -205,7 +203,7 @@ GENERATE MAP ZOOM LEVELS FOR WEBSITE
GENERATE HOUSE IMAGES
-----------------------

1. Do steps 1-6 from **GENERATE WHOLE MAP IMAGES** instruction (above).
1. Do steps 1-6 from **GENERATE PNG IMAGES FROM OTBM** instruction (above).

2. Type in client terminal command:

Expand All @@ -216,22 +214,21 @@ GENERATE HOUSE IMAGES
- **false** - load whole map at once, requires much RAM, set it to **true** to load map by parts,
it's much slower, but will use little amount of RAM to generate house images

**It will freez client for house generation time!** Don't close it. If you want watch progress run OTClient by windows/linux console (not by clicking .exe):
**It will freez client for house generation time!** Don't close it.
If you want watch progress run OTClient by windows/linux console (not by clicking .exe):

./otclient

'Freezed' client will show messages about generated houses in system console.

3. Your house images will appear in your system 'user' directory:
3. Your house images will appear in OTClient directory:

**%HOMEPATH%/otclient/house/** - Windows, open it in folder explorer

**${HOME}/.otclient/house/** - Linux, 'cd' to it, this folder is invisible, but you can navigate to it
**exported_images/house/**

GENERATE FULL MINIMAP FOR OTCLIENT
-----------------------

1. Do steps 1-6 from **GENERATE WHOLE MAP IMAGES** instruction (above).
1. Do steps 1-6 from **GENERATE PNG IMAGES FROM OTBM** instruction (above).

2. Type in client terminal command:

Expand Down
Empty file added exported_images/house/.gitkeep
Empty file.
Empty file added exported_images/map/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions otclientrc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

g_logger.info('Startup done :]')
g_logger.debug("----- STEP 1 -----")
g_logger.info('OTClient Map Generator version: 5')
g_logger.info("prepare client to generate graphics, EXECUTE:")
g_logger.debug("prepareClient(1076, '/things/1076/items.otb', '/map.otbm', 8, 5)")
g_logger.info("'1076' - client version, OTC will load client .spr and .dat from folder 'data/things/1076'")
Expand Down
7 changes: 3 additions & 4 deletions src/client/mapio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
void mapPartGenerator(int x, int y, int z)
{
std::stringstream path;
path << "map/" << x << "_" << y << "_" << z << ".png";
path << "exported_images/map/" << x << "_" << y << "_" << z << ".png";
g_map.drawMap(path.str(), x * 8, y * 8, z, 8);
g_map.increaseGeneratedAreasCount();
}
Expand Down Expand Up @@ -187,7 +187,6 @@ WorkQueue<MapGenWorkItem> queue(1);
void Map::initializeMapGenerator(int threadsNumber)
{
queue.start(threadsNumber);
g_resources.makeDir("map");
g_logger.debug(stdext::format("Started %d map generator threads.", queue.workerCount));
}

Expand Down Expand Up @@ -327,7 +326,7 @@ void Map::drawHouse(uint32 houseId, int houseImageMarginSize)

for (auto floor : floors) {
std::stringstream path;
path << "house/"<< houseId << "_" << floor << ".png";
path << "exported_images/house/"<< houseId << "_" << floor << ".png";
drawMap(path.str(), sx, sy, floor, imageSize, houseId);
}
}
Expand Down Expand Up @@ -376,7 +375,7 @@ void Map::loadOtbm(const std::string& fileName)

uint32 headerMajorItems = root->getU8();
if(headerMajorItems > g_things.getOtbMajorVersion()) {
stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
g_logger.warning(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
headerMajorItems, g_things.getOtbMajorVersion()));
}

Expand Down
121 changes: 8 additions & 113 deletions src/client/thingtype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,119 +326,14 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS

void ThingType::exportImage(std::string fileName, int type)
{
/* types:
0 - normal export
1 - outfit export, all animation frames
2 - outfit export, only first animation frame
3 - items export, first frame of animation
*/
if (m_null)
stdext::throw_exception("cannot export null thingtype");

if (m_spritesIndex.size() == 0)
stdext::throw_exception("cannot export thingtype without sprites");
if (type == 0)
{
/* ORGINAL CODE */
ImagePtr image(new Image(Size(32 * m_size.width() * m_layers * m_numPatternX, 32 * m_size.height() * m_animationPhases * m_numPatternY * m_numPatternZ)));
for (int z = 0; z < m_numPatternZ; ++z) {
for (int y = 0; y < m_numPatternY; ++y) {
for (int x = 0; x < m_numPatternX; ++x) {
for (int l = 0; l < m_layers; ++l) {
for (int a = 0; a < m_animationPhases; ++a) {
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
image->blit(Point(32 * (m_size.width() - w - 1 + m_size.width() * x + m_size.width() * m_numPatternX * l),
32 * (m_size.height() - h - 1 + m_size.height() * y + m_size.height() * m_numPatternY * a + m_size.height() * m_numPatternY * m_animationPhases * z)),
g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)]));
}
}
}
}
}
}
}

image->savePNG(fileName);
}
else if (type == 1)
{
/* OUTFITS ANIM */
/*
patternX = direction
patternY = 0/1/2 = addon none/first/second
patternZ = 0/1 = is sitting on mount no/yes
layer = 0/1 = biala postac / co jak wypelniac
*/
g_resources.makeDir("outfits_anim");
g_resources.makeDir(stdext::format("outfits_anim/%d", getId()));
for (int z = 0; z < m_numPatternZ; ++z) {
for (int y = 0; y < m_numPatternY; ++y) {
for (int x = 0; x < m_numPatternX; ++x) {
for (int l = 0; l < m_layers; ++l) {
for (int a = 0; a < m_animationPhases && a < 8; ++a) {
ImagePtr image(new Image(Size(32 * m_size.width(), 32 * m_size.height())));
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
image->blit(Point(32 * (m_size.width() - w - 1), 32 * (m_size.height() - h - 1)), g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, a)]));
}
}
if (l == 1)
image->savePNG(stdext::format("outfits_anim/%d/%d_%d_%d_%d_template.png", getId(), a + 1, z + 1, y + 1, x + 1));
else
image->savePNG(stdext::format("outfits_anim/%d/%d_%d_%d_%d.png", getId(), a + 1, z + 1, y + 1, x + 1));
}
}
}
}
}
}
else if (type == 2)
{
/* OUTFITS NO ANIM */
/*
patternX = direction
patternY = 0/1/2 = addon none/first/second
patternZ = 0/1 = is sitting on mount no/yes
layer = 0/1 = biala postac / co jak wypelniac
*/
g_resources.makeDir("outfits_no_anim");
g_resources.makeDir(stdext::format("outfits_no_anim/%d", getId()));
for (int z = 0; z < m_numPatternZ; ++z) {
for (int y = 0; y < m_numPatternY; ++y) {
for (int x = 0; x < m_numPatternX; ++x) {
for (int l = 0; l < m_layers; ++l) {
ImagePtr image(new Image(Size(32 * m_size.width(), 32 * m_size.height())));
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
image->blit(Point(32 * (m_size.width() - w - 1), 32 * (m_size.height() - h - 1)), g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, x, y, z, 0)]));
}
}
if (l == 1)
image->savePNG(stdext::format("outfits_no_anim/%d/%d_%d_%d_%d_template.png", getId(), 1, z + 1, y + 1, x + 1));
else
image->savePNG(stdext::format("outfits_no_anim/%d/%d_%d_%d_%d.png", getId(), 1, z + 1, y + 1, x + 1));
}
}
}
}
}
else if (type == 3)
{
/* ITEMS */
g_resources.makeDir("items");

ImagePtr image(new Image(Size(32 * m_size.width(), 32 * m_size.height())));
for (int l = 0; l < m_layers; ++l) {
for (int w = 0; w < m_size.width(); ++w) {
for (int h = 0; h < m_size.height(); ++h) {
image->blit(Point(32 * (m_size.width() - w - 1), 32 * (m_size.height() - h - 1)),
g_sprites.getSpriteImage(m_spritesIndex[getSpriteIndex(w, h, l, 0, 0, 0, 0)]));
}
}
}
image->savePNG(stdext::format("items/%s.png", fileName));
}
g_logger.info("Tools URLs:");
g_logger.info("https://otland.net/threads/items-and-outfits-images-generator-for-website-0-1-1.271231/");
g_logger.info("https://github.com/gesior/open-tibia-library/");
g_logger.info("https://item-images.ots.me/generator/");
g_logger.info("https://item-images.ots.me/generator-animated-items/");
g_logger.info("https://outfit-images.ots.me/generator/");

stdext::throw_exception("EXPORT ITEMS AND OUTFITS USING ONLINE TOOL");
}

void ThingType::unserializeOtml(const OTMLNodePtr& node)
Expand Down
15 changes: 7 additions & 8 deletions src/framework/graphics/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,16 @@ void Image::savePNG(const std::string& fileName)
// empty image, do not save
return;
}
std::ofstream outfile(fileName, std::ofstream::binary);
if (!outfile.is_open() || !outfile.good()) {
g_logger.error(stdext::format("Unable to save image to '%s'", fileName));
return;
}

FileStreamPtr fin = g_resources.createFile(fileName);
if(!fin)
stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName));

fin->cache();
std::stringstream data;
save_png(data, m_size.width(), m_size.height(), 4, (unsigned char*)getPixelData());
fin->write(data.str().c_str(), data.str().length());
fin->flush();
fin->close();
outfile.write(data.str().c_str(), data.str().length());
outfile.close();
}

void Image::cut()
Expand Down

0 comments on commit 1138730

Please sign in to comment.