Because the tiled encrypts parts of TMX

Hello, I would like to know this topic because the tiled encrypts some parts of tmx file with base64, and what has that part?

Need more info. Are you attempting to write your own TMX loader? If so, you simply need a standard base64 implementation (you can surely find one in the available open source readers) to decrypt the tile layer data. That’s the only thing that’s base64 encoded. It can also be zlib/gzip compressed in which case you need to use the zlib library as well.

You can of course disable compression and even base64 encoding but this will create very large TMX files since every tile then has an entry that’s like 20+ characters in the TMX file. Also there’s the option to export to custom formats, be it CSV or your very own format using an export plugin (never done that myself though).

1 Like

Please note that base64 is no “encryption”. It also is no “compression”. base64 is only a way to code arbitrary byte data into a ASCII text. In fact this even requires more space than the original byte data.

For decoding base64 there are many libraries available. I guess searching for <your programming language> decode base64 will lead to you examples of how to do that.

1 Like

I’ll have to point out that Tiled does not “encrypt” any part of the TMX file. It uses standard encoding and compression techniques (base64 and zlib) to keep the file size small.

Storing compressed and encoded binary data is optional. Choose the “CSV” layer data format to avoid it.

1 Like

Thank you all, I did not know this information, now that I know what the tiled converts the data in base64 so that the file stay not so heavy,I wonder what there is in base64, is the part that defines where each tile is?

Yes, it’s the tile layer data, so for each cell on a tile layer it stores a global tile ID, a 32-bit unsigned number pointing at one of the tiles in one of the tilesets associated with the map. You can imagine that for a large tile layer, this will easily be quite a bit of data so the zlib compression often makes sense.

1 Like

It determines in each grid which is right tileset? So these data are enormous and I should not “decrypt” because the data are huge so I should use a way to do this with my right programming language?

Can you stop saying “decrypt”, even when quoted? It’s not encryption. Encryption is for when you want to hide information. :smile:

The data is indeed much larger when decompressed (in fact it’s width * height * 4 bytes), but you’ll have to decompress it to find out which tile layer cell refers to which tile. The point of the compression is just to reduce the file size.

1 Like

I’m sorry, is I’ve learned is that base64 is encryption , and it is now difficult to remove the head, but you know any online tool that converts the base64 so I can read to get a sense of how is it? But if Base64 is not encryption, you could give me some examples of encryption names? Because I got confused

This won’t work, because the base64 encoding is used to store binary data in text form. If you base64-decode it, you get binary data and no text that some online tool would be able to show. Read about how the data should be interpreted on the TMX Map Format page.

Maybe just read the Encryption page on Wikipedia. The naming signifies the purpose of the encoding. base64 is not an encryption because it is not meant to prevent anybody from reading the encoded data. An example encryption algorithm is RSA.

1 Like

Ok thank you, but just one more thing, what are in base64 is like this:<tile gid="0"/>
This code is saying that the tile should be on the first square?
Where is tileset name he is putting?

I have attempted to parse json -> decode base64 -> decompress zlib -> cast byte array to int array. This is my code if you would like to know how it could possibly be done. My code is however not perfect since I am new to this kind of programming :smiley:

There are some things I definitely need to improve, the map size is currently static.

I’m using the libraries:

  1. json
  2. base64
  3. zlib

I have also used the .json format, as opposed to XML which .tmx uses (I think). If you wish to use the .tmx format then you will need a XML parser, but it shouldn’t be difficult to find one.

Everything was done in C++.

//
//  main.cpp
//  Tilemap Reader
//
//  Created by Klas Segeljakt on 15/10/15.
//  Copyright © 2015 Klas Segeljakt. All rights reserved.
//

#include <iostream>

#include <fstream>
#include <string>

#include "json.hpp"
#include "base64.h"
#include "zlib.h"

using json = nlohmann::json;

using namespace std;

int main(int argc, const char * argv[]) {
    
    // Get string from json file
    ifstream t("/Users/Klas/Desktop/testmap_zlib_compressed.json"); // Path to the map file
    stringstream ss;
    ss << t.rdbuf();
    string sd = ss.str();
    
    // Parse json string
    auto j = json::parse(sd);
    
    // Get encoded data
    string encoded = j["layers"][0]["data"];
    
    // Decode encoded data
    string decoded = base64_decode(encoded);
    
    // Set size of uncompressed data
    uLong h = j["layers"][0]["height"];
    uLong w = j["layers"][0]["width"];
    uLong ucompSize = w * h * 4; // Estimate
    
    char uncompressed[8192];
    
    // Uncompress data
    uncompress((Bytef *)uncompressed, &ucompSize, (Bytef *)decoded.c_str(), decoded.size());
    
    // Reinterpret byte array as int array
    int (&result)[1600] = *reinterpret_cast<int(*)[1600]>(uncompressed);
    
    // 'result' array is 1-dimensional, it now needs to be converted into a 2-dimensional array
    // ...

    return 0;
}

Your code snippet is mostly fine, but:

  • You calculate the expected decompressed size, but only allocate a 8k buffer. Then, instead of telling uncompress the actual size of your buffer, you give it the expected size. This can easily lead to a buffer overflow. You’ll want to do char *uncompressed = new char[ucompSize]; instead.

  • Casting the uncompressed char array to an int array only works on little-endian systems. For a more portable approach, see the code snippet on the TMX Map Format page. It also shows a way to iterate the 1-dimensional array in 2-dimensional fashion, so no conversion is needed.

  • Keep in mind that the global tile IDs are unsigned.

1 Like

You can do this in java? For I know not program in C ++ yet

This is some ugly old code, but it implements the above thing in Java:

https://github.com/bjorn/tiled/blob/master/util/java/libtiled-java/src/tiled/io/TMXMapReader.java#L607-L736

1 Like

I Can deduce from this example that is the x and y attribute that I need to put the tile in the correct position, but I try to decompress in java and is returned another kind of different characters, the tiled compressed so in a way that is virtually impossible to decompress, how I do it?

I don’t know what you mean about returning another kind of different characters. Tiled uses plain zlib compression that is definitely not impossible to decompress. In Java you can decompress it with an InflaterInputStream, as demonstrated by the code I linked previously.